mirror of
https://github.com/krahets/hello-algo.git
synced 2026-11-02 03:05:24 +08:00
* Retranslate the complete Japanese online edition from Chinese * Fit Japanese homepage labels and localize heading permalinks * Point Japanese contribution instructions to the Japanese preview * Replace locale conditionals with multilingual UI tables
3.2 KiB
3.2 KiB
分割統治による探索戦略
すでに学んだように、探索アルゴリズムは大きく二つに分類できます。
- 全探索:データ構造を走査して探索し、時間計算量は
O(n)です。 - 適応的探索:データの特有の編成方法や事前情報を利用し、時間計算量を $O(\log n)$、さらには
O(1)にできます。
実際、時間計算量が O(\log n) の探索アルゴリズムは、通常、分割統治戦略に基づいています。二分探索や木がその例です。
- 二分探索は各ステップで、問題(配列内で目的の要素を探すこと)を小さな問題(配列の半分で目的の要素を探すこと)に分解します。配列が空になるか、目的の要素が見つかるまで続けます。
- 木は分割統治の代表例です。二分探索木、AVL 木、ヒープなどのデータ構造では、各種操作の時間計算量が
O(\log n)になります。
二分探索の分割統治戦略は、次のように整理できます。
- 問題を分解できる:中央の要素と目的の要素を比較することで、元の問題(配列内での探索)を部分問題(配列の半分での探索)に再帰的に分解します。
- 部分問題が独立している:二分探索では各回に一つの部分問題だけを扱い、ほかの部分問題の影響を受けません。
- 部分問題の解を統合する必要がない:二分探索の目的は特定の要素を見つけることなので、部分問題の解を統合する必要はありません。部分問題が解けると、元の問題も同時に解けます。
分割統治によって探索効率が上がる本質的な理由は、全探索では 1 回に一つの候補しか除外できないのに対し、分割統治による探索では 1 回に候補の半分を除外できることです。
分割統治による二分探索の実装
前の章では、二分探索を反復処理(イテレーション)で実装しました。ここでは、分割統治(再帰)で実装します。
!!! question
長さ $n$ のソート済み配列 `nums` が与えられます。すべての要素は互いに異なります。要素 `target` を探してください。
分割統治の観点から、探索区間 [i, j] に対応する部分問題を f(i, j) と表します。
元の問題 f(0, n-1) から始め、次の手順で二分探索を行います。
- 探索区間
[i, j]の中央mを求め、それを使って探索区間の半分を除外します。 - 大きさが半分になった部分問題
f(i, m-1)またはf(m+1, j)を再帰的に解きます。 - 手順
1.と2.を繰り返し、targetが見つかるか、区間が空になったら戻ります。
下図に、配列内の要素 6 を二分探索する際の分割統治の流れを示します。
実装では、問題 f(i, j) を解く再帰関数 dfs() を定義します。
[file]{binary_search_recur}-[class]{}-[func]{binary_search}
