二分探索と一般的な実装 (C++ および Python)
二分探索は、順序付けられた配列内の特定の要素を見つけるためのアルゴリズムです。ターゲット値と配列の中央の要素を比較して、要素の半分を削除します。ターゲット値が中央の要素より小さい場合、検索は配列の左半分で続行されます。ターゲット値が中央の要素より大きい場合、検索は配列の右半分で続行されます。ターゲット値が等しい場合、検索は配列の右半分で続行されます。中央の要素に移動すると、ターゲット値が見つかります。ターゲット値が見つかるまで、またはターゲット値が配列内に存在しないと判断されるまで、このプロセスを繰り返します。通常、二分検索では、検索対象の配列が順序付けされている必要があります。線形探索と比較して、二分探索はより効率的です。
二分探索はデータが整然としていることが前提であり、具体的な実装方法としては再帰実装と反復実装があります。二分探索に適用されると、再帰的実装は、ターゲット要素が見つかるか検索範囲が空になるまで、検索範囲を徐々に狭めます。反復実装では、ループを使用して、ターゲット要素が見つかるか検索範囲が空になるまで検索範囲を更新します。
再帰と反復については次のとおりです。
再帰:
再帰は、問題をより小さなサブ問題に分割して解決する方法です。再帰では、関数はそれ自体を呼び出して、基本ケース (再帰終了条件とも呼ばれます) に達するまで同じタイプの部分問題を解決し、その後、すべての部分問題の解を組み合わせて最終結果を取得します。再帰の鍵は、再帰終了条件と再帰呼び出しのプロセスを見つけることです。
再帰的アルゴリズムの重要な概念は「自己相似性」です。つまり、問題の解決策は、1 つ以上の小さな類似した部分問題を解決することによって得られます。
反復:
反復とは、目的の結果が得られるまでループを通じて一連の操作を繰り返し実行する方法です。反復では、問題の解決策が順序付けられた一連のステップに分割され、目標の状態または条件に到達するまで各ステップで問題の状態が変化します。反復は通常、ループ構造 (for ループ、while ループなど) を使用して実装されます。
二分探索は、順序付き配列または順序付きリスト内のターゲット値を迅速に見つけることができる効率的な検索アルゴリズムです。次の 2 つの一般的な実装方法を以下に紹介します。
二分探索の再帰的実装
1. 検索範囲の下端 (左境界とも呼ばれます) と上限 (右境界とも呼ばれます) を決定します。これらは、最初は配列の最初の要素と最後の要素です。
2. 中間要素のインデックス Mid を計算します: Mid = Low + (High - Low) / 2。
3. 中央の要素がターゲット値と等しい場合は、そのインデックスを返します。
4. 中央の要素がターゲット値より大きい場合、左半分の検索を続行します。二分検索関数を再帰的に呼び出し、検索範囲の右境界を Mid - 1 に更新します。
5. 中央の要素がターゲット値より小さい場合は、右半分の検索を続けます。二分検索関数を再帰的に呼び出し、検索範囲の左境界を Mid + 1 に更新します。
6. 左側の境界が右側の境界より大きい場合は、ターゲット値が見つからないことを意味し、-1 が返されます。
二分探索反復の実装
1. 検索範囲の下限と上限を決定します。最初は配列の最初の要素と最後の要素です。
2. ループの終了条件は、左側の境界が右側の境界以下であることです。
3. ループ内で、中間要素のインデックス Mid を計算します: Mid = low + (high - low) / 2。
4. 中央の要素がターゲット値と等しい場合は、そのインデックスを返します。
5. 中央の要素がターゲット値より大きい場合、検索範囲の右境界を Mid - 1 に更新します。
6. 中央の要素が目標値より小さい場合、検索範囲の左境界をmid + 1に更新します。
7. ループの終了時に左境界が右境界より大きい場合、ターゲット値が見つからないことを意味し、-1 が返されます。
上記 2 つの実装方法は、順序付けされた配列または順序付けされたリストに基づいて検索を行い、検索範囲を継続的に絞り込むことで目的の値を迅速に見つけます。再帰的実装では再帰関数呼び出しを使用して検索プロセスを実装しますが、反復的実装ではループを使用して反復検索を実行します。どちらの方法の時間計算量も O(log n) です。
以下は、再帰アルゴリズムと反復アルゴリズムを実装する C++ と Python の二分探索のコード例です。
★二分探索 C++ 再帰アルゴリズムの実装:
#include <iostream>
using namespace std;
int binarySearchRecursive(int arr[], int low, int high, int target) {
if (low > high) {
return -1; // 没有找到目标值,返回-1
}
int mid = low + (high - low) / 2;
if (arr[mid] == target) {
return mid; // 找到目标值,返回索引
} else if (arr[mid] > target) {
return binarySearchRecursive(arr, low, mid - 1, target); // 在左半部分继续查找
} else {
return binarySearchRecursive(arr, mid + 1, high, target); // 在右半部分继续查找
}
}
int main() {
int arr[] = {1, 3, 5, 7, 9, 11};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 3; //
int result = binarySearchRecursive(arr, 0, n - 1, target);
if (result == -1) {
cout << "Target not found" << endl;
} else {
cout << "Target found at index: " << result << endl;
}
return 0;
}
ヒント: C++ では、sizeof(arr) / sizeof(arr[0]) で 1 次元配列の長さを取得できます。
★Pythonの再帰アルゴリズムの実装
def binarySearchRecursive(arr, low, high, target):
if low > high:
return -1 # 没有找到目标值,返回-1
mid = low + (high - low) // 2
if arr[mid] == target:
return mid # 找到目标值,返回索引
elif arr[mid] > target:
return binarySearchRecursive(arr, low, mid - 1, target) # 在左半部分继续查找
else:
return binarySearchRecursive(arr, mid + 1, high, target) # 在右半部分继续查找
arr = [1, 3, 5, 7, 9, 11]
target = 3
result = binarySearchRecursive(arr, 0, len(arr) - 1, target)
if result == -1:
print("Target not found")
else:
print("Target found at index:", result)
★C++反復アルゴリズムの実装:
#include <iostream>
using namespace std;
int binarySearchIterative(int arr[], int low, int high, int target) {
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) {
return mid; // 找到目标值,返回索引
} else if (arr[mid] < target) {
low = mid + 1; // 在右半部分继续查找
} else {
high = mid - 1; // 在左半部分继续查找
}
}
return -1; // 没有找到目标值,返回-1
}
int main() {
int arr[] = {1, 3, 5, 7, 9, 11};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 3;
int result = binarySearchIterative(arr, 0, n - 1, target);
if (result == -1) {
cout << "Target not found" << endl;
} else {
cout << "Target found at index: " << result << endl;
}
return 0;
}
★Python反復アルゴリズムの実装:
def binarySearchIterative(arr, low, high, target):
while low <= high:
mid = low + (high - low) // 2
if arr[mid] == target:
return mid # 找到目标值,返回索引
elif arr[mid] < target:
low = mid + 1 # 在右半部分继续查找
else:
high = mid - 1 # 在左半部分继续查找
return -1 # 没有找到目标值,返回-1
arr = [1, 3, 5, 7, 9, 11]
target = 3
result = binarySearchIterative(arr, 0, len(arr) - 1, target)
if result == -1:
print("Target not found")
else:
print("Target found at index:", result)
上記のコード例は、C++ 言語と Python 言語を使用して、それぞれ再帰アルゴリズムと反復アルゴリズムの二分探索を実装する方法を示しています。どちらも核となるアイデアは二分探索テンプレート アルゴリズムであり、実装方法が異なりますが、原理は同じです。