C++でソート済み配列から「kより大きい要素」の個数を求める方法
この問題では、N個のソート済み整数からなる配列 arr[] と整数 k が与えられます。目的は、配列内で k より大きい要素の個数を求めることです。
問題例
入力
arr[] = {1, 2, 5, 7, 8, 9}、k = 4出力
4
説明
k = 4 より大きい要素は 5, 7, 8, 9 の4つ
解法1:線形探索(シンプルな方法)
最も単純な解法は、配列の先頭から末尾までループで走査し、k より大きい最初の要素が見つかった時点で処理を止める方法です。その位置以降に残っている要素の数が、求める個数となります。
実装例
#include <iostream>
using namespace std;
int findGreaterCount(int arr[], int n, int k){
for(int i = 0; i < n; i++){
if(arr[i] > k)
return (n - i);
}
return -1;
}
int main(){
int arr[] = { 1, 3, 5, 7, 7, 8, 12, 21};
int n = sizeof(arr) / sizeof(arr[0]);
int k = 5;
cout<<"The number of elements greater than k is "<<findGreaterCount(arr, n, k);
return 0;
}出力
The number of elements greater than k is 5
このコードは正しく動作しますが、計算量は O(N) となり、配列サイズが大きい場合には非効率です。
解法2:二分探索(効率的な方法)
配列がすでにソートされていることを活かせば、二分探索を使って k より大きい要素の中で最小の位置(境界)を O(log N) で見つけられます。見つかった位置から配列末尾までの要素数が答えになります。
アルゴリズムの流れ
探索範囲の中央値が k より大きければ、その位置を候補として記録し、左半分をさらに探索します。k 以下であれば右半分へ移動します。これを繰り返すことで、k を超える要素が最初に現れるインデックスを特定できます。
実装例
#include <iostream>
using namespace std;
int findGreaterCount(int arr[], int n, int k){
int s = 0;
int e = n - 1;
int firstGreterEle = n;
while (s <= e) {
int mid = s + (e - s) / 2;
if (arr[mid] > k) {
firstGreterEle = mid;
e = mid - 1;
}
else
s = mid + 1;
}
return (n - firstGreterEle);
}
int main(){
int arr[] = { 1, 3, 5, 7, 7, 8, 12, 21};
int n = sizeof(arr) / sizeof(arr[0]);
int k = 5;
cout<<"The number of elements greater than k is "<<findGreaterCount(arr, n, k);
return 0;
}出力
The number of elements greater than k is 5
まとめ
| 手法 | 時間計算量 | 特徴 |
|---|---|---|
| 線形探索 | O(N) | 実装が簡単だが大規模データに不向き |
| 二分探索 | O(log N) | ソート済み配列なら高速に境界を特定可能 |
ソート済み配列が前提となるこの問題では、二分探索を用いることで大幅な高速化が期待できます。同様の考え方は、C++標準ライブラリの std::upper_bound でも実現できるため、実務ではこちらを活用するのも有効です。
-
C++で配列内の数値の頻度(出現回数)を求める方法
配列に n 個の異なる要素が格納されているとします。この配列の中から、特定の要素が何回出現するか(頻度)を調べたい場合があります。例えば、配列 A = [5, 12, 26, 5, 3, 4, 15, 5, 8, 4] の中で「5」の頻度を調べると、答えは 3 になります。アルゴリズムの考え方この問題は、次の手順で解くことができます。1. 配列を左端から順に走査します。2. 現在の要素が調べたい数値と一致したら、カウンターを1つ増やします。3. 一致しない場合は、そのまま次の要素へ進みます。4. 配列の最後まで走査したら、カウンターの値が頻度となります。このアルゴリズムの計算量は O(n) で
-
C++で回転ソート済み配列の回転回数を求める方法
ここでは、回転ソート済み配列(Rotated Sorted Array)が与えられたときに、その配列を元のソートされた状態に戻すために必要な回転回数を求める問題を扱います。なお、回転は「右から左へ」要素を移動させる操作として考えます。例えば、次のような配列を考えてみましょう。{15, 17, 1, 2, 6, 11}この配列をソートするには、2回の回転が必要です。回転を繰り返すと、最終的に次の順序になります。{1, 2, 6, 11, 15, 17}この場合の出力(回転回数)は 2 となります。解法のポイントこの問題のロジックは非常にシンプルです。配列を注意深く観察すると、必要な回転回数は「最