C++で配列内の不動点(インデックスと等しい値)を二分探索で効率的に検索する方法
本記事では、ソート済みの配列から「不動点(Fixed Point)」と呼ばれる特殊な要素を検索する方法を解説します。不動点とは、要素の値がそのインデックス(添字)と一致している要素のことです。プログラムは不動点が存在すればその値を返し、存在しない場合は -1 を返します。なお、配列には負の数が含まれることもあり、データ要素はソート済みであると仮定します。
二分探索による効率的なアプローチ
すべての要素を順に確認する線形探索では O(n) の計算量が必要ですが、配列がソート済みであるという性質を利用すると、二分探索(バイナリサーチ)によって O(log n) という高速な計算量でこの問題を解くことができます。アルゴリズムの流れは以下の通りです。
- まず配列の中央の要素を確認し、その値がインデックスと一致していれば、それが不動点なのでその値を返します。
- 一致しない場合、中央のインデックスがその位置の値より大きければ、不動点は右側の領域に存在する可能性があるため、右半分に対して同じ処理を再帰的に行います。
- 逆に、インデックスが値より小さい場合は、不動点は左側にある可能性が高いため、左半分を探索します。
- 探索範囲がなくなった場合は不動点が存在しないと判断し、-1 を返します。
C++での実装例
以下が、二分探索を再帰的に実装したC++のコード例です。
#include<iostream>
using namespace std;
// 二分探索で不動点を探す再帰関数
int getFixedPoint(int arr[], int left, int right) {
if(right >= left){
int mid = (left + right)/2; // 中央のインデックスを計算
if(mid == arr[mid]) // 値とインデックスが一致 → 不動点
return mid;
if(mid > arr[mid]) // インデックスが値より大きければ右側を探索
return getFixedPoint(arr, (mid + 1), right);
else // そうでなければ左側を探索
return getFixedPoint(arr, left, (mid -1));
}
return -1; // 不動点が見つからない場合
}
int main() {
int arr[] = {-10, -1, 0, 3, 10, 11, 9, 50, 56};
int n = sizeof(arr)/sizeof(arr[0]);
cout<<"Fixed Point: "<< getFixedPoint(arr, 0, n-1);
}実行結果
Fixed Point: 3
この例では、インデックス 3 の位置に値 3 が格納されているため、不動点として 3 が出力されます。
計算量について
このアルゴリズムの時間計算量は O(log n) です。各ステップで探索範囲が半分に絞られていくため、要素数が多い配列でも高速に動作します。空間計算量は再帰呼び出しに伴うスタックの使用により O(log n) となりますが、ループによる反復実装に書き換えれば O(1) に抑えることも可能です。
-
C++で括弧文字列からイコールポイント(等分点)を見つける方法
この記事では、C++を使って括弧の文字列からイコールポイント(等分点)を求める方法を解説します。 イコールポイントとは? イコールポイントとは、あるインデックス i において、その位置より前にある開き括弧「(」の数と、その位置以降にある閉じ括弧「)」の数が等しくなる地点のことです。 例として、次の括弧文字列を考えてみましょう。 (()))( ()()() )) ) → 元の文字列は (()))(()()()))) この文字列を詳しく観察すると、インデックス0〜9の範囲に含まれる開き括弧は5個、インデックス9〜14の範囲に含まれる閉じ括弧も5個あります。したがって、インデックス9がこの文字列の
-
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! =