This commit is contained in:
krahets
2026-03-30 08:17:41 +08:00
parent 68cafe99dd
commit 46bccf0065
484 changed files with 60193 additions and 20315 deletions
@@ -6,7 +6,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="アニメーション図解ワンクリック実行データ構造とアルゴリズムチュートリアル">
<meta name="description" content="アニメーション図解ワンクリック実行コードで学べるデータ構造とアルゴリズムの入門書">
<meta name="author" content="krahets">
@@ -39,7 +39,7 @@
<title>12.1 分割統治アルゴリズム - Hello アルゴリズム</title>
<title>12.1 分割統治 - Hello アルゴリズム</title>
@@ -117,7 +117,7 @@
<path
d="M480 32c0-12.9-7.8-24.6-19.8-29.6s-25.7-2.2-34.9 6.9L381.7 53c-48 48-113.1 75-181 75H192 160 64c-35.3 0-64 28.7-64 64v96c0 35.3 28.7 64 64 64l0 128c0 17.7 14.3 32 32 32h64c17.7 0 32-14.3 32-32V352l8.7 0c67.9 0 133 27 181 75l43.6 43.6c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6V300.4c18.6-8.8 32-32.5 32-60.4s-13.4-51.6-32-60.4V32zm-64 76.7V240 371.3C357.2 317.8 280.5 288 200.7 288H192V192h8.7c79.8 0 156.5-29.8 215.3-83.3z" />
</svg>
<span>日本語版審閱者を募集しています!詳細<a href="https://github.com/krahets/hello-algo/blob/main/ja/CONTRIBUTING.md">CONTRIBUTING.md</a>参照してください。</span>
<span>日本語版のレビュアーを募集しています。詳しく<a href="/ja/chapter_appendix/contribution/">こちら</a>ご覧ください。</span>
</div>
</div>
@@ -152,7 +152,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
12.1 &nbsp; 分割統治アルゴリズム
12.1 &nbsp; 分割統治
</span>
</div>
@@ -341,7 +341,7 @@
<span class="md-ellipsis">
はじめに
@@ -358,7 +358,7 @@
<span class="md-nav__icon md-icon"></span>
はじめに
</label>
@@ -618,7 +618,7 @@
<span class="md-ellipsis">
1.1 &nbsp; アルゴリズムはどこにでもある
1.1 &nbsp; アルゴリズムは至るところにある
@@ -646,7 +646,7 @@
<span class="md-ellipsis">
1.2 &nbsp; アルゴリズムとは何か
1.2 &nbsp; アルゴリズムとは
@@ -783,7 +783,7 @@
<span class="md-ellipsis">
2.1 &nbsp; アルゴリズム効率評価
2.1 &nbsp; アルゴリズム効率評価
@@ -1060,7 +1060,7 @@
<span class="md-ellipsis">
3.3 &nbsp; 数値の符号化 *
3.3 &nbsp; 数値エンコーディング *
@@ -1088,7 +1088,7 @@
<span class="md-ellipsis">
3.4 &nbsp; 文字の符号化 *
3.4 &nbsp; 文字エンコーディング *
@@ -1591,7 +1591,7 @@
<span class="md-ellipsis">
第 6 章 &nbsp; ハッシュ
第 6 章 &nbsp; ハッシュテーブル
@@ -1613,7 +1613,7 @@
<span class="md-nav__icon md-icon"></span>
第 6 章 &nbsp; ハッシュ
第 6 章 &nbsp; ハッシュテーブル
</label>
@@ -1635,7 +1635,7 @@
<span class="md-ellipsis">
6.1 &nbsp; ハッシュ
6.1 &nbsp; ハッシュテーブル
@@ -1942,7 +1942,7 @@
<span class="md-ellipsis">
7.5 &nbsp; AVL木 *
7.5 &nbsp; AVL 木 *
@@ -2105,7 +2105,7 @@
<span class="md-ellipsis">
8.2 &nbsp; ヒープ構築操作
8.2 &nbsp; ヒープ構築
@@ -2491,7 +2491,7 @@
<span class="md-ellipsis">
10.2 &nbsp; 二分探索の挿入
10.2 &nbsp; 二分探索の挿入位置
@@ -2547,7 +2547,7 @@
<span class="md-ellipsis">
10.4 &nbsp; ハッシュ最適化戦略
10.4 &nbsp; ハッシュによる最適化戦略
@@ -2575,7 +2575,7 @@
<span class="md-ellipsis">
10.5 &nbsp; 探索アルゴリズムの再認識
10.5 &nbsp; 探索アルゴリズム再考
@@ -3124,7 +3124,7 @@
<span class="md-ellipsis">
12.1 &nbsp; 分割統治アルゴリズム
12.1 &nbsp; 分割統治
@@ -3142,7 +3142,7 @@
<span class="md-ellipsis">
12.1 &nbsp; 分割統治アルゴリズム
12.1 &nbsp; 分割統治
@@ -3172,7 +3172,7 @@
<a href="#1211" class="md-nav__link">
<span class="md-ellipsis">
12.1.1 &nbsp; 分割統治問題を特定する方法
12.1.1 &nbsp; 分割統治法の問題を見極めるには
</span>
</a>
@@ -3183,19 +3183,19 @@
<a href="#1212" class="md-nav__link">
<span class="md-ellipsis">
12.1.2 &nbsp; 分割統治による効率の向上
12.1.2 &nbsp; 分割統治法で効率を高める
</span>
</a>
<nav class="md-nav" aria-label="12.1.2 分割統治による効率の向上">
<nav class="md-nav" aria-label="12.1.2 分割統治法で効率を高める">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#1" class="md-nav__link">
<span class="md-ellipsis">
1. &nbsp; 操作数の最適化
1. &nbsp; 操作数の最適化
</span>
</a>
@@ -3206,7 +3206,7 @@
<a href="#2" class="md-nav__link">
<span class="md-ellipsis">
2. &nbsp; 並列計算による最適化
2. &nbsp; 並列計算最適化
</span>
</a>
@@ -3222,7 +3222,7 @@
<a href="#1213" class="md-nav__link">
<span class="md-ellipsis">
12.1.3 &nbsp; 分割統治の一般的な応用
12.1.3 &nbsp; 分割統治法の代表的な応用
</span>
</a>
@@ -3280,7 +3280,7 @@
<span class="md-ellipsis">
12.3 &nbsp; 木の構築問題
12.3 &nbsp; 二分木の構築問題
@@ -3308,7 +3308,7 @@
<span class="md-ellipsis">
12.4 &nbsp; ハノイの塔問題
12.4 &nbsp; ハノイの塔問題
@@ -3501,7 +3501,7 @@
<span class="md-ellipsis">
13.3 &nbsp; 部分集合和問題
13.3 &nbsp; 部分和問題
@@ -3529,7 +3529,7 @@
<span class="md-ellipsis">
13.4 &nbsp; Nクイーン問題
13.4 &nbsp; n クイーン問題
@@ -3670,7 +3670,7 @@
<span class="md-ellipsis">
14.1 &nbsp; 動的計画法の初歩
14.1 &nbsp; 動的計画法入門
@@ -3698,7 +3698,7 @@
<span class="md-ellipsis">
14.2 &nbsp; DP 問題特性
14.2 &nbsp; 動的計画法の問題特性
@@ -3726,7 +3726,7 @@
<span class="md-ellipsis">
14.3 &nbsp; DP の解法の考え方
14.3 &nbsp; 動的計画法の問題解決の考え方
@@ -3754,7 +3754,7 @@
<span class="md-ellipsis">
14.4 &nbsp; 0-1ナップサック問題
14.4 &nbsp; 0-1 ナップサック問題
@@ -3947,7 +3947,7 @@
<span class="md-ellipsis">
15.1 &nbsp; 貪欲アルゴリズム
15.1 &nbsp; 貪欲
@@ -4192,7 +4192,7 @@
<span class="md-ellipsis">
16.2 &nbsp; 一緒に作に参加する
16.2 &nbsp; 一緒に作に参加しましょう
@@ -4338,7 +4338,7 @@
<a href="#1211" class="md-nav__link">
<span class="md-ellipsis">
12.1.1 &nbsp; 分割統治問題を特定する方法
12.1.1 &nbsp; 分割統治法の問題を見極めるには
</span>
</a>
@@ -4349,19 +4349,19 @@
<a href="#1212" class="md-nav__link">
<span class="md-ellipsis">
12.1.2 &nbsp; 分割統治による効率の向上
12.1.2 &nbsp; 分割統治法で効率を高める
</span>
</a>
<nav class="md-nav" aria-label="12.1.2 分割統治による効率の向上">
<nav class="md-nav" aria-label="12.1.2 分割統治法で効率を高める">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#1" class="md-nav__link">
<span class="md-ellipsis">
1. &nbsp; 操作数の最適化
1. &nbsp; 操作数の最適化
</span>
</a>
@@ -4372,7 +4372,7 @@
<a href="#2" class="md-nav__link">
<span class="md-ellipsis">
2. &nbsp; 並列計算による最適化
2. &nbsp; 並列計算最適化
</span>
</a>
@@ -4388,7 +4388,7 @@
<a href="#1213" class="md-nav__link">
<span class="md-ellipsis">
12.1.3 &nbsp; 分割統治の一般的な応用
12.1.3 &nbsp; 分割統治法の代表的な応用
</span>
</a>
@@ -4432,45 +4432,45 @@
<!-- Page content -->
<h1 id="121">12.1 &nbsp; 分割統治アルゴリズム<a class="headerlink" href="#121" title="Permanent link">&para;</a></h1>
<p><u>分割統治</u>は重要で人気のあるアルゴリズム戦略です。名前が示すように、アルゴリズムは通常再帰に実装され、「分」と「治」の2つのステップから構成されます。</p>
<h1 id="121">12.1 &nbsp; 分割統治<a class="headerlink" href="#121" title="Permanent link">&para;</a></h1>
<p><u>分割統治法(divide and conquer</u>は、問題を分けて統べるという意味であり、非常に重要で一般的なアルゴリズム戦略です。分割統治法は通常再帰に基づいて実装され、「分」と「治」の 2 つのステップから構成されます。</p>
<ol>
<li><strong>(分割段階)</strong>:元の問題を再帰的に2つ以上の小さな部分問題に分解し、最小の部分問題に到達するまで続けます。</li>
<li><strong>治(マージ段階)</strong>:解決方法が既知の最小の部分問題から開始し、部分問題の解をボトムアップ方式でマージして元の問題の解を構築します。</li>
<li><strong>分(分割段階)</strong>:元の問題を 2 つ以上の部分問題へ再帰的に分解し、最小の部分問題に到達した時点で停止します。</li>
<li><strong>治(統合段階)</strong>:解が既知である最小の部分問題から始めて、部分問題の解を下から上へ統合し、元の問題の解を構築します。</li>
</ol>
<p>以下の図に示すように、「マージソート」は分割統治戦略の典型的な応用の一つです。</p>
<ol>
<li><strong></strong>:元の配列(元の問題)を再帰的に2つの副配列(部分問題)に分割し、副配列が1つの要素のみになるまで(最小の部分問題)続けます。</li>
<li><strong></strong>順序付けられた副配列(部分問題の解)をボトムアップでマージして、順序付けられた元の配列(元の問題の解)を取得します。</li>
<li><strong></strong>:元の配列(元の問題)を 2 つの部分配列(部分問題)へ再帰的に分割し、部分配列に要素が 1 つだけ残るまで続けます。</li>
<li><strong></strong>整列済みの部分配列(部分問題の解)を下から上へ統合し、整列済みの元の配列(元の問題の解)をます。</li>
</ol>
<p><img alt="マージソートの分割統治戦略" class="animation-figure" src="../divide_and_conquer.assets/divide_and_conquer_merge_sort.png" /></p>
<p align="center"> 図 12-1 &nbsp; マージソートの分割統治戦略 </p>
<h2 id="1211">12.1.1 &nbsp; 分割統治問題を特定する方法<a class="headerlink" href="#1211" title="Permanent link">&para;</a></h2>
<p>問題が分割統治解決に適しているかどうかは、通常以下の基準に基づいて決定できます。</p>
<h2 id="1211">12.1.1 &nbsp; 分割統治法の問題を見極めるには<a class="headerlink" href="#1211" title="Permanent link">&para;</a></h2>
<p>ある問題が分割統治法で解くのに適しているかどうかは、通常、次の判断基準を参考にできます。</p>
<ol>
<li><strong>問題をより小さなものに分解できる</strong>:元の問題より小さく類似した部分問題に分でき、そのような過程を同じ方法で再帰的に実行できます。</li>
<li><strong>部分問題は独立している</strong>:部分問題に重複がなく、独立しており、個別に解決できます。</li>
<li><strong>部分問題の解をマージできる</strong>:元の問題の解は、部分問題の解を組み合わせることで導出されます。</li>
<li><strong>問題分解できる</strong>:元の問題は、より小さく類似した部分問題に分でき、同じ方法で再帰的に分割できます。</li>
<li><strong>部分問題は独立している</strong>:部分問題同士に重複がなく、相互依存もないため、独立して解決できます。</li>
<li><strong>部分問題の解は統合できる</strong>:元の問題の解は、部分問題の解を統合することで得られます。</li>
</ol>
<p>明らかに、マージソートはこれら3つの基準を満たしています。</p>
<p>明らかに、マージソートは以上の 3 つの判断基準を満たしています。</p>
<ol>
<li><strong>問題をより小さなものに分解できる</strong>:配列(元の問題)を再帰的に2つの副配列(部分問題)に分割します。</li>
<li><strong>部分問題は独立している</strong>:各配列は独立してソートできます(部分問題は独立して解決できます)。</li>
<li><strong>部分問題の解をマージできる</strong>2つの順序付けられた副配列(部分問題の解)を1つの順序付けられた配列(元の問題の解)にマージできます。</li>
<li><strong>問題分解できる</strong>:配列(元の問題)を 2 つの部分配列(部分問題)へ再帰的に分割します。</li>
<li><strong>部分問題は独立している</strong>:各部分配列は独立ソートできます(部分問題は独立に解けます)。</li>
<li><strong>部分問題の解は統合できる</strong>2 つの整列済み部分配列(部分問題の解)は、1 つの整列済み配列(元の問題の解)に統合できます。</li>
</ol>
<h2 id="1212">12.1.2 &nbsp; 分割統治による効率の向上<a class="headerlink" href="#1212" title="Permanent link">&para;</a></h2>
<p><strong>分割統治戦略はアルゴリズム問題を効果的に解決するだけでなく、しばしば効率を向上させます</strong>。ソートアルゴリズムでは、クイックソート、マージソート、ヒープソートは、分割統治戦略を適用しているため、選択ソート、バブルソート、挿入ソートより高速です。</p>
<p>私たちの心には疑問があるかもしれません:<strong>なぜ分割統治はアルゴリズム効率を向上させることができ、その根本的な論理は何ですか?</strong> つまり、問題を部分問題に分解し、それらを解決し、それらの解を組み合わせて元の問題に対処することが、元の問題を直接解決するより効率的である理由は何ですか?この質問は2つの側面から分析できます:操作数と並列計算</p>
<h3 id="1">1. &nbsp; 操作数の最適化<a class="headerlink" href="#1" title="Permanent link">&para;</a></h3>
<p>「バブルソート」を例にると、長さ <span class="arithmatex">\(n\)</span> の配列を処理するのに <span class="arithmatex">\(O(n^2)\)</span> 時間が必要です。以下の図に示すように、配列を中点から2つの副配列に分割するとします。そのような分割には <span class="arithmatex">\(O(n)\)</span> 時間が必要です。各副配列のソートには <span class="arithmatex">\(O((n / 2)^2)\)</span> 時間が必要です。そして2つの副配列のマージには <span class="arithmatex">\(O(n)\)</span> 時間が必要です。したがって、全体の時間計算量は:</p>
<h2 id="1212">12.1.2 &nbsp; 分割統治法で効率を高める<a class="headerlink" href="#1212" title="Permanent link">&para;</a></h2>
<p><strong>分割統治はアルゴリズム問題を効果的に解るだけでなく、多くの場合アルゴリズムの効率も高められます</strong>。ソートアルゴリズムでは、クイックソート、マージソート、ヒープソート選択ソート、バブルソート、挿入ソートより高速ですが、これは分割統治戦略を適用しているためです</p>
<p>ここで次の疑問が生じます。<strong>なぜ分割統治はアルゴリズム効率を高められるのでしょうか。その根本的な仕組みは何でしょうか</strong>?言い換えると、大きな問題を複数の部分問題に分解し、部分問題を解き、それらの解を統合して元の問題の解にするという手順は、なぜ元の問題を直接解より効率的なのでしょうか。この問題は、操作回数と並列計算の 2 つの観点から議論できます</p>
<h3 id="1">1. &nbsp; 操作数の最適化<a class="headerlink" href="#1" title="Permanent link">&para;</a></h3>
<p>「バブルソート」を例にると、長さ <span class="arithmatex">\(n\)</span> の配列を処理するのに <span class="arithmatex">\(O(n^2)\)</span> 時間がかかります。以下の図ように、配列を中央で 2 つの部分配列に分けると仮定すると、分割には <span class="arithmatex">\(O(n)\)</span> 時間、各部分配列のソートには <span class="arithmatex">\(O((n / 2)^2)\)</span> 時間、2 つの部分配列の統合には <span class="arithmatex">\(O(n)\)</span> 時間が必要で、全体の時間計算量は次のようになります</p>
<div class="arithmatex">\[
O(n + (\frac{n}{2})^2 \times 2 + n) = O(\frac{n^2}{2} + 2n)
\]</div>
<p><img alt="配列分割前後のバブルソート" class="animation-figure" src="../divide_and_conquer.assets/divide_and_conquer_bubble_sort.png" /></p>
<p align="center"> 図 12-2 &nbsp; 配列分割前後のバブルソート </p>
<p>以下の不等式を計算してみましょう。左側は分割前の総操作数を表し、右側は分割後の操作数をそれぞれ表します:</p>
<p>次に、以下の不等式を計算します。左辺と右辺はそれぞれ、分割前と分割後の操作総数です:</p>
<div class="arithmatex">\[
\begin{aligned}
n^2 &amp; &gt; \frac{n^2}{2} + 2n \newline
@@ -4478,36 +4478,36 @@ n^2 - \frac{n^2}{2} - 2n &amp; &gt; 0 \newline
n(n - 4) &amp; &gt; 0
\end{aligned}
\]</div>
<p><strong>これは <span class="arithmatex">\(n &gt; 4\)</span>場合、分割後の操作数が少なく、より良いパフォーマンスにつながることを意味します</strong>。分割後の時間計算量は依然として二次 <span class="arithmatex">\(O(n^2)\)</span>すが、計算量の定数係数が減少していることに注意してください</p>
<p>さらに進むことができます。<strong>配列をその中点からさらに2つの副配列に分割し続けて、副配列が1つの要素のみになるまで続けたらどうでしょうか?</strong> このアイデアは実際には「マージソート」で、時間計算量は <span class="arithmatex">\(O(n \log n)\)</span> です。</p>
<p>少し違うことを試してみましょう。<strong>2つではなく、より多くの分割に分割したらどうでしょうか?</strong> 例えば、元の配列を <span class="arithmatex">\(k\)</span> 個の配列に均等に分割しますか?このアプローチは「バケットソート」と非常に似ており、大量データのソートに非常に適しています。理論的には、時間計算量は <span class="arithmatex">\(O(n + k)\)</span> に達することができます。</p>
<h3 id="2">2. &nbsp; 並列計算による最適化<a class="headerlink" href="#2" title="Permanent link">&para;</a></h3>
<p>分割統治によって生成される部分問題は互いに独立していることが分かっています。<strong>これは、それらを並列で解決できることを意味します</strong> その結果、分割統治はアルゴリズムの時間計算量を減らすだけでなく、<strong>現代のオペレーティングシステムによる並列最適化も促進します。</strong></p>
<p>並列最適化は、複数のコアやプロセッサを持つ環境で特に効果的です。システムが複数の部分問題を同時に処理できるため、計算リソースを完全に活用し、全体的な実行時間大幅に短縮されます。</p>
<p>えば、以下の図に示す「バケットソート」では、大量のデータを様々なバケットに均等に分解します。各バケットのソート作業は、利用可能な計算ユニットに割り当てることができます。すべての作業が完了すると、すべてのソートされたバケットがマージされて最終結果が生成されます。</p>
<p><strong>これは<span class="arithmatex">\(n &gt; 4\)</span>ときに分割後の操作回数の方が少なくなり、ソート効率が高くなることを意味します</strong>ただし、分割後の時間計算量は依然として 2 次の <span class="arithmatex">\(O(n^2)\)</span>あり、計算量の定数項が小さくなっただけです</p>
<p>さらに考えると、<strong>部分配列を中央からさらに 2 つの部分配列へと分割し続け</strong>、部分配列に要素が 1 つだけ残るまで分割を止めないとしたらどうでしょうか。この考え方がまさに「マージソート」であり、時間計算量は <span class="arithmatex">\(O(n \log n)\)</span> です。</p>
<p>さらに、<strong>分割点をいくつか増やして</strong>、元の配列を平均的に <span class="arithmatex">\(k\)</span> 個の部分配列に分けるとしたらどうでしょうか。この状況は「バケットソート」と非常によく似ており、大量データのソートに非常に適しています。理論上の時間計算量は <span class="arithmatex">\(O(n + k)\)</span> に達ます。</p>
<h3 id="2">2. &nbsp; 並列計算最適化<a class="headerlink" href="#2" title="Permanent link">&para;</a></h3>
<p>分割統治法で生成される部分問題は互いに独立しているため、<strong>通常は並列に解くことができます</strong>。つまり、分割統治はアルゴリズムの時間計算量を下げられるだけでなく、<strong>オペレーティングシステム並列最適化にも有利です</strong></p>
<p>並列最適化は、マルチコアまたはマルチプロセッサ環境で特に効です。システムが複数の部分問題を同時に処理でき、計算資源をより十分に活用できるため、全体実行時間大幅に短縮できます。</p>
<p>たとえば、以下の図に示す「バケットソート」では、大量のデータをバケットに均等に割り当てることで、すべてのバケットのソート処理を各計算ユニットに分散し、完了後に結果を統合できます。</p>
<p><img alt="バケットソートの並列計算" class="animation-figure" src="../divide_and_conquer.assets/divide_and_conquer_parallel_computing.png" /></p>
<p align="center"> 図 12-3 &nbsp; バケットソートの並列計算 </p>
<h2 id="1213">12.1.3 &nbsp; 分割統治の一般的な応用<a class="headerlink" href="#1213" title="Permanent link">&para;</a></h2>
<p>分割統治は多くの古典的なアルゴリズム問題を解決するために使用できます。</p>
<h2 id="1213">12.1.3 &nbsp; 分割統治法の代表的な応用<a class="headerlink" href="#1213" title="Permanent link">&para;</a></h2>
<p>一方では、分割統治は多くの古典的なアルゴリズム問題を解くのに使えます。</p>
<ul>
<li><strong>最近点対の発見</strong>:このアルゴリズムは点の集合を2つの半分に分割することで動作します。そして各半分で再帰的に最近点対を見つけます。最後に、2つの半分にまたがるペアを考慮して、全体の最近点対を見つけます。</li>
<li><strong>大整数乗算</strong>一つのアルゴリズムはKaratsubaと呼ばれます。大整数の乗算をいくつかの小さな整数の乗算と加算に分解します。</li>
<li><strong>行列乗算</strong>一例はStrassenアルゴリズムです。大きな行列の乗算を複数の小さな行列の乗算と加算に分解します。</li>
<li><strong>ハノイの塔問題</strong>:ハノイの塔問題は再帰的に解決でき、分割統治戦略の典型的な応用です。</li>
<li><strong>転倒対の解決</strong>シーケンスで、前の数が後の数より大きい場合、これら2つの数は転対を構成します。転倒対問題の解決は、マージソートの助けを借りて、分割統治のアイデアを利用できます。</li>
<li><strong>最近点対探索</strong>:このアルゴリズムは、まず点集合を 2 つに分け、それぞれの部分における最近点対を求め、最後に 2 つの部分をまたぐ最近点対を求めます。</li>
<li><strong>大整数乗算</strong>たとえば Karatsuba 法では、大整数の乗算を、より小さな整数どうしのいくつかの乗算と加算に分解します。</li>
<li><strong>行列乗算</strong>たとえば Strassen 法では、大きな行列の乗算を複数の小さな行列の乗算と加算に分解します。</li>
<li><strong>ハノイの塔問題</strong>:ハノイの塔問題は再帰によって解くことができ、これは典型的な分割統治戦略の応用です。</li>
<li><strong>反転対の計算</strong>ある数列で前の数が後の数より大きい場合、その 2 つの数は転対を構成します。反転対の問題は、分割統治の考え方を利用し、マージソートを用いて解けます。</li>
</ul>
<p>分割統治はアルゴリズムとデータ構造の設計にも広く応用されています。</p>
<p>他方で、分割統治はアルゴリズムとデータ構造の設計にも非常に広く応用されています。</p>
<ul>
<li><strong>二分探索</strong>:二分探索は、ソート済み配列を中インデックスから2つの半分に分割します。そして、ターゲット値と中要素の比較結果に基づいて、一方の半分が破棄されます。同じプロセスで残りの半分で検索が続行され、ターゲットが見つかるか残りの要素がなくなるまで続きます。</li>
<li><strong>マージソート</strong>この節の冒頭ですでに紹介したため、さらなる詳述は不要です</li>
<li><strong>クイックソート</strong>:クイックソートはピボット値を選択して配列を2つの副配列に分割し、一方はピボットより小さい要素、もう一方はピボットより大きい要素を持ちます。このプロセスは、これら2つの副配列のそれぞれに対して、1つの要素のみを保持するまで続ます。</li>
<li><strong>バケットソート</strong>:バケットソートの基本的なアイデアは、データを複数のバケットに分散させることです。各バケット内の要素をソートした後、バケットから順序よく要素を取得して順序付けられた配列を取得します。</li>
<li><strong></strong>えば二分探索木、AVL木、赤黒木、B木、B+木など。その操作(検索、挿入削除)はすべて分割統治戦略の応用と見なすことができます。</li>
<li><strong>ヒープ</strong>:ヒープは特別なタイプの完全二分木です。その様々な操作(挿入、削除、ヒープ化は、実際に分割統治のアイデアを含意しています。</li>
<li><strong>ハッシュテーブル</strong>:ハッシュテーブルは直接分割統治を適用しませんが、一部のハッシュ衝突解決ソリューションは間接的にこの戦略を適用します。えば、チェイン法の長いリストは、クエリ効率を向上させるために赤黒木変換される場合があります。</li>
<li><strong>二分探索</strong>:二分探索は、整列済み配列を中央のインデックスで 2 つに分け、目標値と中要素の比較結果に基づいてどちらの半区間を除外するかを決め、残った区間で同じ二分操作を行います。</li>
<li><strong>マージソート</strong>節の冒頭で紹介したため、ここでは繰り返しません</li>
<li><strong>クイックソート</strong>:クイックソートは基準値を 1 つ選び、配列を、基準値より小さい要素の部分配列と、基準値より大きい要素の部分配列に分け、その後それぞれに対して同じ分割操作を行い、部分配列に要素が 1 つだけ残るまで続ます。</li>
<li><strong>バケットソート</strong>:バケットソートの基本的な考え方は、データを複数のバケットに分散し、各バケット内の要素をソートしたうえで、各バケットの要素を順に取り出して整列済み配列を得ることです。</li>
<li><strong>構造</strong>たとえば二分探索木、AVL 木、赤黒木、B 木、B+ 木などでは、探索・挿入削除などの操作をいずれも分割統治戦略の応用とみなせます。</li>
<li><strong>ヒープ</strong>:ヒープは特殊な完全二分木であり、挿入、削除、ヒープ化などの各種操作には、実際に分割統治の考え方が含まれています。</li>
<li><strong>ハッシュテーブル</strong>:ハッシュテーブル自体は分割統治を直接適用しているわけではありませんが、いくつかのハッシュ衝突解決法では間接的に分割統治戦略が使われています。たとえば、連鎖アドレス法における長い連結リストは、検索効率を高めるために赤黒木変換されます。</li>
</ul>
<p>**分割統治は巧妙に浸透するアルゴリズムアイデア**であり、様々なアルゴリズムデータ構造に組み込まれていることが分かります。</p>
<p>このように、**分割統治法は「静かに物を潤す」ようなアルゴリズム思想**であり、さまざまなアルゴリズムデータ構造の中に潜んでいます。</p>
<!-- Source file information -->