【C++】指定した要素を削除した後に最小値を見つける方法
この記事では、2つの配列 arr[] と del[] が与えられたときに、del[] に含まれる要素を arr[] から削除した後の最小値を見つける問題を解説します。
具体的には、arr[] の値のうち del[] にも存在するものを取り除き、削除後の配列における最小値を出力します。なお、重複した値については del[] に出現する回数分だけ削除され、それ以外は残る点に注意が必要です。
例で問題を確認しよう
入力:
arr[] = {2, 5, 6, 9, 1}
del[] = {1, 5, 9}
出力:
2
この例では、arr[] から 1・5・9 が削除されるため、残った値の中で最も小さい 2 が結果となります。
解決アプローチ:ハッシュを活用する
この問題に対するシンプルかつ効率的な解法がハッシュ(ハッシュマップ)を使う方法です。手順は以下の通りです。
- まず、
del[]配列のすべての値をハッシュテーブルに挿入します(このとき各値の出現回数もカウントしておきます)。 - 次に、
arr[]を先頭から走査し、各値がハッシュテーブルに存在するかを確認します。 - 存在する場合は削除対象なのでスキップし、ハッシュ内のカウントを1減らします。カウントが0になったらエントリを削除します。
- 存在しない場合は候補となる値なので、現在の最小値(minVal)より小さければ更新します。
- 最終的に得られた minVal が答えとなります。
この手法により、重複した値を含む場合でも、指定された回数だけ正確に要素を削除することが可能です。
実装例
上記の解法の動作を示すC++プログラムは以下の通りです。
#include <bits/stdc++.h>
using namespace std;
int findSmallestVal(int arr[], int m, int del[], int n){
unordered_map<int, int> delVals;
for (int i = 0; i < n; ++i) {
delVals[del[i]]++;
}
int minVal = INT_MAX;
for (int i = 0; i < m; ++i) {
if (delVals.find(arr[i]) != delVals.end()) {
delVals[arr[i]]--;
if (delVals[arr[i]] == 0)
delVals.erase(arr[i]);
}
else
minVal = min(minVal, arr[i]);
}
return minVal;
}
int main(){
int array[] = { 5, 12, 33, 4, 56, 12, 20 };
int m = sizeof(array) / sizeof(array[0]);
int del[] = { 12, 4, 56, 5 };
int n = sizeof(del) / sizeof(del[0]);
cout<<"The smallest value after the deleting element is "<<findSmallestVal(array, m, del, n);
return 0;
}
出力
The smallest value after the deleting element is 12
実行結果の解説
このサンプルコードでは、arr[] に 12 が2回登場しますが、del[] には 12 が1回しか含まれていないため、削除されるのは最初の1つだけです。したがって、削除後に残る最小値は 12 となります。このように、ハッシュで出現回数を管理することで、重複を含むケースでも正しく動作させることができます。
まとめ
本記事では、配列から指定要素を削除した後に最小値を求める問題について、ハッシュマップを利用した解法を紹介しました。時間計算量は O(m + n)(m は arr[] の要素数、n は del[] の要素数)となり、非常に効率的です。重複データの扱い方にも触れましたので、同様のアルゴリズム問題を解く際の参考にしてください。
-
C++で指定された差分を持つペアを見つける方法
はじめに 配列 A に n 個の異なる要素が格納されているとします。この配列から、2つの要素 x と y の差が指定された値 d と一致するようなペア (x, y) をすべて見つける必要があります。 例として、配列が A = [10, 15, 26, 30, 40, 70]、指定された差分が 30 である場合を考えます。このとき、該当するペアは (10, 40) と (40, 70) です。 解法:ツーポインタ法 この問題は、配列が昇順にソートされていることを前提とすれば、ツーポインタ(二重インデックス)法を使って効率的に解くことができます。まず、1つ目のポインタ「i」を先頭の要素に、2つ目の
-
C++で配列要素の階乗の最大公約数(GCD)を求める方法
N個の要素を持つ配列Aが与えられたとき、配列内のすべての要素の階乗の最大公約数(GCD)を求めることを考えます。例えば、配列の要素が {3, 4, 8, 6} の場合、各要素の階乗は 3! = 6、4! = 24、8! = 40320、6! = 720 となり、これらのGCDは 6 になります。解法のポイントここで重要な数学的な性質があります。2つの数のGCDとは、両方の数を割り切る最大の数のことです。階乗の場合、小さい数の階乗は必ず大きい数の階乗を割り切ることができます。つまり、2つの階乗のGCDは、小さい方の数の階乗そのものになります。例えば、3! と 5! のGCDを考えると、3! =