アルゴリズム

乱択アルゴリズム徹底解説:計算量を劇的に改善する「ランダム性」の力

2025年6月12日

皆さんは「ランダム」という言葉を聞いて、どんなイメージを持つでしょうか?おそらく、サイコロを振る、ルーレットが回る、宝くじを引く、といった予測不能な出来事を思い浮かべるかもしれません。ゲームやギャンブルの世界では、この予測不能性が面白さを生み出す要素となっています。

実は、コンピューターのアルゴリズムの世界でも、「ランダム性」は非常に強力なツールとなり得ます。通常、アルゴリズムはどんな入力に対しても正しい答えを効率的に出すように設計されます。しかし、時には「意地悪な入力」が存在し、特定のアルゴリズムの効率を著しく低下させることがあります。例えば、数字当てゲームで1から100までの数値を順番に当てることを考えると、もし隠された数が91だった場合、91回質問する必要があり、非常に非効率です。

このような「意地悪な入力」を回避したり、あるいは問題そのものが持つ「ランダムな性質」を巧みに利用したりすることで、驚くほど効率的なアルゴリズムを構築できることがあります。

本記事では、「ランダム性」をアルゴリズム設計と解析の強力なツールとして捉え、以下の2つの主要なトピックを通して、その魅力を探求します。

  1. 乱択アルゴリズム (Randomized Algorithms): アルゴリズム自身がランダムな選択を行うことで、どんな入力に対しても(期待値として)効率的なパフォーマンスを達成する手法。

  2. 確率的解析 (Probabilistic Analysis): アルゴリズムは決定的だが、入力が特定の確率分布に従うと仮定し、その平均的なパフォーマンスを解析する手法。

まずは、皆さんも親しみやすいゲームを通して、乱択アルゴリズムのアイデアに触れてみましょう。

乱択アルゴリズム

数当てゲームとランダム性の力

1から100までの整数が書かれたカードが10枚あります。その中の1枚を選んで、書かれた数を当てれば「当たり」です。あなたは質問をすることができます。例えば「64ですか?」と質問して、当たったかどうかを教えてもらいます。

このゲーム、何回質問すれば平均的に当てられるでしょうか?

一番シンプルな戦略は、ランダムに1~100の中から1つの数を言い続ける、というものです。もし、カードに書かれた数が10, 34, 40, 60, 62, 63, 70, 80, 85, 90のいずれかだった場合、あなたはこれらの数のどれか1つを当てるまで、ランダムな数を言い続けます。

あなたが1回の質問で当たりを引く確率は、当たりが10種類あるので10/100 = 1/10です。外れる確率は90/100 = 9/10です。

質問回数を \(Q\) とすると、 \(Q=1\) 回で当たる確率は \(1 / 10\) です。 \(Q=2\) 回で当たる確率は、 1 回目に外れて 2 回目に当たる確率なので \((9 / 10) \times(1 / 10)\) です。 \(Q=k\) 回で当たる確率は \((9 / 10)^{k-1} \times(1 / 10)\) です。
期待される質問回数は、これらの確率の和となります。

$$
E[Q]=\sum_{k=1}^{\infty} k \cdot\left(\frac{9}{10}\right)^{k-1} \cdot \frac{1}{10}
$$

これは幾何分布の期待値の形です。成功確率 \(p=1 / 10\) の場合の期待値は \(1 / p\) なので、

$$
E[Q]=\frac{1}{1 / 10}=10
$$

となります。平均的には10回の質問で当たりを引けると期待できます。実際の質問回数は運によって変わりますが、確率分布を見ると、質問回数は平均値 である10回のあたりに最も集中し、それよりずっと多くなる確率は急速に減少します。

しかし、なぜ「ランダムに選ぶ」ことが重要なのでしょうか?もしランダムではない、決定的な戦略をとるとどうなるか考えてみましょう。

決定的な戦略1:1, 2, 3, ... と順番に質問する
もしカードの数が1だったら1回で当たります。しかし、もしカードの数が91だったら、91回質問する必要があります。最悪ケースでは100回(カードにない数を選び続けた場合)や、運悪く90以下の数を質問し尽くして最後に残った数が91だった場合など、非常に多くの回数がかかります。特に、もしカードに書かれた数が意図的に(例えば、あなたの戦略を知っている人が)大きな数を選んでいた場合、この戦略は非常に非効率になります。

決定的な戦略2:100, 99, 98, ... と逆順に質問する
今度はカードの数が100だったら1回で当たります。しかし、もしカードの数が10だったら、91回質問する必要があります。やはり意地悪な入力に対しては非効率です。

このように、決定的なアルゴリズムは、入力の性質(この場合はカードに書かれた数の選び方)によっては極端に効率が悪くなる(最悪ケース)可能性があります。一方、ランダムな戦略は、入力によらず(平均的に見れば)安定したパフォーマンスを示すことが期待できます。今回のゲームでは、ランダムに選ぶ戦略は、平均10回で当たりを引くことが保証されます。カードの数の選び方がどんなに意地悪でも、あなたのランダムな選択によってその意地悪さを「かき混ぜて」しまうからです。

このような「サイコロを振る(乱数を使う)」ことで、問題を効率的に解ける(あるいは効率的に解析できる)アルゴリズムを乱択アルゴリズム (Randomized Algorithm) と呼びます。

乱択アルゴリズムは、その振る舞いが入力だけでなく、乱数発生器によって生成される値によっても決定されます。乱数発生器としては、例えばRANDOM(a, b)のように、aとbを含む範囲の整数を一様な確率で返すものを利用できると仮定します。(実際には、多くのプログラミング環境では擬似乱数発生器が使われます。これは統計的にランダムに見える決定的なアルゴリズムです。)

乱択アルゴリズムの性能を評価する際には、乱数発生器が返す値の分布にわたる実行時間の期待値を評価します。これを期待実行時間 (expected running time) と呼びます。入力がランダムなアルゴリズムの平均ケースの実行時間 (average-case running time) とは区別されます。一般に、確率分布がアルゴリズムへの入力にかかる場合は平均ケースの実行時間について議論し、アルゴリズム自体がランダムな選択を行う場合は期待実行時間について議論します。

乱択アルゴリズムの例:Quick Select

次に、乱択アルゴリズムの力をより本格的な問題で見てみましょう。

問題

\(N\) 個の整数 \(a_1, a_2, \ldots, a_N\) が与えられます。この中で \(K\) 番目に小さい数は?

例えば、 \(24,58,49,77,81,36,53\) という 7 つの数があり、 \(K=4\) 番目に小さい数を求める場合を考えます。数を小さい順に並べると \(24,36,49,53,58,77,81\) となり、4番目に小さい数は 53 です。

この問題を解く最も簡単な方法は、与えられた配列をソートすることです。ソートされた配列のK番目の要素が答えになります。マージソートやクイック ソートなど、多くの効率的なソートアルゴリズムは \(O(N \log N)\) の計算量でこれを実現できます。これは決定的なアルゴリズムとしては非常に高速です。

しかし、乱数を使うことで、平均計算量(average complexity)が \(O(N)\) になるアルゴリズムが存在します。それがQuick Selectです。Quick Selectは、ソ —トのアルゴリズムであるQuick Sortと似たアイデアに基づいています。

Quick Selectのアイデア

  1. 与えられた配列の中から、ランダムに1つの値(ピボット)を選びます。
  2. 選んだピボットを基準に、配列の要素を「ピボットより小さい要素のグループ」と「ピボット以上の要素のグループ」に分割します。この分割操作 (パーティション)は \(O(N)\) の時間で可能です。
  3. ピボット自体の最終的な順位が分かります。例えば、ピボットより小さい要素が \(S\) 個あったとすると、ピボットは全体で \((S+1)\) 番目に小さい数です。 もし求めている \(K\) 番目の数が、ピボットの順位と一致すれば、ピボットが答えです。
  4. もし \(K\) 番目の数がピボットより小さいグループにあるなら、そのグループの中から \(K\) 番目に小さい数を求める問題に帰着します。
  5. もし \(K\) 番目の数がピボットより大きいグループにあるなら、そのグループの中から \(K\) 番目に小さい数を求める問題に帰着します。ただし、K番目の数 は、元の問題におけるピボットの順位を考慮して、グループ内での相対的な順位に変換する必要があります。

Quick Selectの動き

例 : \(53,58,24,77,81,49,90,37,19\) の中から \(K=5\) 番目に小さい数を求める。

①ランダムに1つの値を選びます。例えば37を選んだとします。

②37をピボットに分割します。「37より小さいグループ」 \(\{24,19\}\) 、「37」自身、「37より大きいグループ」 \(\{53,58,77,81,49,90\}\) 。

③グループごとに並べると、 \(\{24,19\}, 37,\{53,58,77,81,49,90\}\) となります。37より小さい要素が2個あるので、37は3番目に小さい数です。

④求めたいのは5番目に小さい数です。37は3番目なので、5番目の数は「37より大きいグループ」の中にあります。問題は「 \(\{53,58,77,81,49,90\}\) の中から、元のリストで5番目に小さい数」に帰着しました。37が3番目だったので、このグループの中では \((5-3)=2\) 番目に小さい数を探せばよいことになります。

⑤新しい問題「6個の中から2番目に小さい数」に対して、再びランダムにピボットを選び、分割...を繰り返します。

疑似コード

Quick Selectの計算量解析

このアルゴリズムの計算量は、どのピボットが選ばれるかに依存します。

最悪ケース

もし毎回ピボットとして配列の最小値や最大値を選んでしまうと、分割後の小さい方のグループが常にサイズ1になってしまい、再帰的に解く問題のサイズが1つしか減りません。この場合、計算量は \(N+(N-1)+(N-2)+\cdots+1=O\left(N^2\right)\) となり、ソートより悪くなってしまいます。

平均ケース(期待計算時間)

Quick Selectの強みは、ランダムにピボットを選ぶことで、意図的に最悪ケースの入力を作るのが不可能になる点です。ランダムなピボ ットは、平均的には配列の中央付近の値になる可能性が高く、これにより分割後のグループのサイズが大きく偏る可能性は低くなります。 より厳密な解析(詳細は割愛しますが)によると、ランダムなピボットを選んだ場合、各ステップで問題のサイズが平均して定数倍(例えぱ0.75倍以下)に縮小することが示されます。例えば、サイズ \(N\) の問題が、 \(0.75 N 、 0.75^2 N 、 0.75^3 N 、 \ldots\) と縮小していくと考えると、全体の計算量は \(N+0.75 N+0.75^2 N+\cdots=N\left(1+0.75+0.75^2+\ldots\right)\) という等比級数の和になります。初項1、公比 0.75 の無限等比級数の和は \(1 /(1-0.75)=1 / 0.25=4\) なので、全体の計算量は \(O(4 N)=O(N)\) となります。

平均計算量が線形時間であることの証明

Quick Select アルゴリズムの平均計算量が \(O(N)\) であることを、再帰的な期待実行時間の漸化式を用いて厳密に証明します。

配列のサイズを \(N\) とします。目標は、この配列の \(K\) 番目に小さい要素を見つけることです。

Quick Select のステップは以下の通りです。
1. 配列の中から要素を一つ、ランダムに選び、これをピボットとします。
2. ピボットを使って配列を分割 (partition) します。ピボットより小さい要素をピボットの左に、ピボットより大きい要素をピボットの右に集めます。ピボット自身は正しい位置に置かれます。この分割操作にかかる時間は配列のサイズに比例し、\(O(N)\) です。
3. ピボットが全体で \(k\) 番目に小さい要素であると分かったとします(ピボットの順位が \(k\))。
4. もし \(K = k\) なら、ピボットが求めていた要素です。アルゴリズムは終了します。
5. もし \(K < k\) なら、求めている \(K\) 番目の要素はピボットより小さい要素のグループ(サイズ \(k-1\)) の中にあります。このグループに対して再帰的に Quick Select を呼び出し、\(K\) 番目に小さい要素を探します。
6. もし \(K > k\) なら、求めている \(K\) 番目の要素はピボットより大きい要素のグループ(サイズ \(N-k\)) の中にあります。このグループに対して再帰的に Quick Select を呼び出し、そのグループの中で \((K-k)\) 番目に小さい要素を探します。

Quick Select の計算量は、主に分割操作にかかる時間です。各再帰呼び出しで、新しい(より小さい)配列に対して分割を行います。全体の計算量は、これらの分割操作にかかる時間の合計です。

\(T(N)\) を、サイズ \(N\) の配列に対して Quick Select が必要とする期待実行時間とします。
ステップ1とステップ2にかかる時間は \(O(N)\) です。これはある定数 \(c\) を用いて \(cN\) 以下で抑えられるとします。
ステップ3以降は、ピボットの順位 \(k\) に依存する再帰呼び出しです。ピボットは配列からランダムに選ばれるので、その順位 \(k\) は 1 から \(N\) までのいずれかを取り得ます。ピボットが \(N\) 個の要素の中からランダムに選ばれる場合、各要素がピボットになる確率は \(1/N\) です。そして、もし特定の要素がピボットに選ばれた場合、その要素の順位は配列をソートしたときの順位と一致します。したがって、ピボットの順位が \(k\) である確率も \(1/N\) です(\(k=1, 2, \ldots, N\))。

ピボットの順位が \(k\) である場合の、再帰呼び出しの期待コストは、その次に解くべき部分問題のサイズに依存します。
- ピボットの順位が \(k\),かつ \(K = k\) の場合:終了。再帰なし。コスト \(O(1)\)。
- ピボットの順位が \(k\),かつ \(K < k\) の場合:サイズ \(k-1\) の部分問題に対して Quick Select を解く。期待コスト \(T(k-1)\)。
- ピボットの順位が \(k\),かつ \(K > k\) の場合:サイズ \(N-k\) の部分問題に対して Quick Select を解く。期待コスト \(T(N-k)\)。

\(T(N)\) に関する漸化式は、ピボットの順位 \(k\) の全ての可能性に対する期待値を平均して求められます。
$$T(N) = O(N) + \sum_{k=1}^{N} \frac{1}{N} \times \begin{cases} O(1) & \text{if } K = k \\ T(k-1) & \text{if } K < k \\ T(N-k) & \text{if } K > k \end{cases}$$
簡単のため、\(O(N)\) 項を \(cN\) とし、\(O(1)\) 項は \(cN\) に吸収されるほど小さいと見なせます。また、\(K\) は固定された値ですが、漸化式を単純化するために、最悪の場合の再帰サイズを考えます。ピボットの順位が \(k\) のとき、次に解く部分問題のサイズは \(\max(k-1, N-k)\) 以下です。この最大サイズに対する期待時間を上界として考えます。
$$T(N) \le cN + \sum_{k=1}^{N} \frac{1}{N} T(\max(k-1, N-k))$$
ここで、\(T(0)\) はベースケースであり、\(O(1)\) です(例えば \(T(0)=c_0\) とします)。

和の項を評価します。\(k\) が 1 から \(N\) まで変化するとき、\(\max(k-1, N-k)\) は \(N-1, N-2, \ldots, \max(\lfloor N/2 \rfloor-1, N-\lfloor N/2 \rfloor), \ldots, N-2, N-1\) という値をとります。
具体的には、\(\max(k-1, N-k) = j\) となるのは、\(k-1=j\) か \(N-k=j\) の場合です。
\(k = j+1\) のとき、\(N-k = N-(j+1) = N-j-1\) です。このとき \(\max(j, N-j-1)\) となります。
\(N-k = j\) のとき、\(k = N-j\) です。このとき \(\max(N-j-1, j)\) となります。
したがって、サイズ \(j\) の部分問題が発生する可能性があるのは、ピボットの順位 \(k-1\) が \(j\) になるか、ピボットの順位 \(N-k\) が \(j\) になる場合です。

より単純に、\(\max(k-1, N-k)\) の値 \(j\) は、\(k\) が \(1\) や \(N\) に近いときは \(N-1\) に近く、\(k\) が \(N/2\) に近いときは \(N/2\) に近くなります。
和 \(\sum_{k=1}^{N} T(\max(k-1, N-k))\) は、\(\max(k-1, N-k)\) の値が小さい項から並べ替えると、大体 \(2 \sum_{j=\lfloor N/2 \rfloor}^{N-1} T(j)\) となります(\(j \ge \lfloor N/2 \rfloor\) となる各サイズ \(j\) は、おおよそ2つの \(k\) の値に対応するため)。

したがって、漸化式は次のように近似できます。
$$T(N) \le cN + \frac{2}{N} \sum_{j=\lfloor N/2 \rfloor}^{N-1} T(j)$$
ここで、この漸化式が \(T(N) \le aN\) という線形な解を持つことを、代入法(または帰納法)で示します。ある定数 \(a\) が存在して、全ての \(j < N\) に対して \(T(j) \le aj\) が成り立つと仮定します。この仮定が \(T(N)\) でも成り立つような \(a\) を見つけます。
$$T(N) \le cN + \frac{2}{N} \sum_{j=\lfloor N/2 \rfloor}^{N-1} aj$$
$$T(N) \le cN + \frac{2a}{N} \sum_{j=\lfloor N/2 \rfloor}^{N-1} j$$
和 \(\sum_{j=\lfloor N/2 \rfloor}^{N-1} j\) を評価します。これは、約 \(N/2\) 個の項を持つ等差数列の和であり、項の値は \(\lfloor N/2 \rfloor\) から \(N-1\) までです。
この和は、積分 \(\int_{N/2}^{N} x \, dx\) で上から近似できます。
$$ \sum_{j=\lfloor N/2 \rfloor}^{N-1} j \le \int_{\lfloor N/2 \rfloor}^{N} x \, dx \le \int_{N/2}^{N} x \, dx = \left[ \frac{x^2}{2} \right]_{N/2}^{N} = \frac{N^2}{2} - \frac{(N/2)^2}{2} = \frac{N^2}{2} - \frac{N^2}{8} = \frac{3N^2}{8} $$
(厳密には、和と積分の関係でもう少し正確な評価が必要ですが、ここではオーダーを示すための簡略化としてこれを用います。)
したがって、
$$T(N) \le cN + \frac{2a}{N} \left( \frac{3N^2}{8} \right) = cN + \frac{3aN}{4}$$
我々は \(T(N) \le aN\) となるような \(a\) を見つけたいので、
$$aN \ge cN + \frac{3aN}{4}$$
$$aN - \frac{3aN}{4} \ge cN$$
$$\frac{aN}{4} \ge cN$$
$$a \ge 4c$$
\(a\) を \(4c\) 以上の任意の定数として選べば(例えば \(a = 4c\))、帰納法の仮定が \(N\) に対しても成り立ちます。ベースケース \(T(0)=c_0\) や \(T(1)\) などに対して \(T(N) \le aN\) が成り立つように、十分に大きな \(a\) を選んでおく必要があります(例えば \(a = \max(4c, T(1)/1, T(0)/0 \text{ if N>0})\) のように)。

この証明により、Quick Select の期待計算時間は \(O(N)\) であることが厳密に示されました。これは、ランダムなピボット選択によって、最悪ケースになりうるピボットが選ばれる確率が低く、平均的には問題のサイズが十分に小さくなるためです。特に、漸化式における和の項が \(1/N\) 倍されることが重要であり、これにより線形な結合で抑えられます。

「平均して定数倍に縮小する」という表現は、厳密には「次に再帰呼び出しされる部分問題のサイズの期待値が、元のサイズの定数倍以下になる」という意味ではありません。実際、\(E[\max(k-1, N-k)]\) は \(N\) に近い値になります。しかし、全ての可能な再帰サイズの期待値の和が、\(N\) に対して線形になることが、この \(O(N)\) の期待計算時間を保証するのです。□

 

Quick Selectの期待計算時間は \(O(N)\) です。これは、ソートの \(O(N \log N)\) よりも高速であり、ランダム性によって最悪ケースの入力を回避し、平均的に優れた性能を達成できる乱択アルゴリズムの好例です。

採用問題(秘書問題)

ランダム性を用いたアルゴリズムと解析の導入例として、採用問題を詳しく見てみましょう。

問題設定

新しいオフィスアシスタントを一人雇う必要があります。あなたは職業紹介所に依頼し、紹介所は毎日一人ずつ候補者を送ってきます(合計 \(n\) 人)。あなた は各候補者と面接し、その場でその候補者を「雇う」か「雇わない(拒否する)」かを決定します。

戦略

あなたは常に、それまで面接した中で最も優秀な人物を雇うという方針をとります。面接後、その候補者が現在のオフィスアシスタントよりも優秀であれば、現在のオフィスアシスタントを解雇し、新しい候補者を雇います。最初の候補者は、他の候補者よりも能力の低いダミー候補者(候補者0)と比較されます。

これを擬似コードで表したのが、以下の決定的な手続き HIRE-ASSISTANT(n) です。候補者は1からnまで番号が付けられ、その順番に面接されます。

※この擬似コードは、候補者iがそれまでに見た中で最高の候補者かどうかを常に判断できると仮定しています。これは、候補者の能力に全順序が存在することを意味します。

コストモデル

この問題では、アルゴリズムの実行時間そのものではなく、面接と採用にかかる費用に注目します。

  • 面接にかかるコストは比較的低く、1人あたり \(c_i\) とします。
  • 採用にかかるコストは高く、1人採用するたびに \(c_h\) とします。新しい人を雇うたびに、現在のオフィスアシスタントを解雇し、紹介所に手数料を支払う必要があるためです。

\(m\) 人を雇った場合の総コストは \(O\left(c_i n+c_h m\right)\) となります。あなたは常に \(n\) 人全員と面接するため、面接コスト \(c_i n\) は固定です。したがって、私たちは主 こ採用コスト \(c_h m\) に焦点を当てて分析します。この費用(雇われる人の数 \(m\) )は、候補者が面接に現れる順序に依存します。

最悪ケース分析

最も費用がかさむ最悪のケースは、面接した候補者全員を実際に雇う場合です。これは、候補者が厳密に能力の高い順に現れた場合に発生します(例:候補者1が最も能力が低く、候補者 \(n\) が最も能力が高い)。この場合、最初の候補者以外は全員、それまでの誰よりも優秀なので、面接するたびに新しい候補者が雇われます。これにより、 \(n\) 人全員が採用されることになり、 \(m=n\) となります。最悪ケースの総採用コストは \(O\left(c_i n+c_h n\right)=O\left(\left(c_i+c_h\right) n\right)\) 、特に採用コストだけ見れば \(O\left(c_h n\right)\) となります。

確率的解析のアプローチ

しかし、候補者が能力の高い順に来るとは限りません。実際、候補者がどのような順序で来るか、あなたは知る由もないかもしれません。そこで、典型的なケース や平均的なケースで何が起こるかを分析するために、確率的解析の手法を用います。
確率的解析では、入力が特定の確率分布に従うと仮定し、その分布全体にわたるアルゴリズムのパフォーマンス(この場合は採用コスト)の平均(期待値)を計算します。
採用問題では、候補者の能力に全順序が存在すると仮定し、各候補者を 1 から \(n\) までの一意のランクで評価できるとします。そして、これらの候補者がラン ダムな順序(一様ランダム順列)で面接に現れると仮定します。つまり、 \(n!\) 個の可能な順列のそれぞれが等しい確率で発生すると仮定します。この仮定の もとで、決定的な手続きHIRE-ASSISTANTを実行した場合に雇われる人の数の期待値を計算します。この解析結果を平均ケースの採用コストと呼びます。後のセクションで詳しく分析するように、この期待値は約 \(\ln n\) となり、平均ケースの採用コストは \(O\left(c_h \ln n\right)\) となります。

乱択アルゴリズムのアプローチ

もし候補者がランダムな順序で来るという保証が得られない場合、私たちは入力の分布に頼る確率的解析を行うことはできません。しかし、私たちはアルゴリズムをランダム化することで、入力の順序に対する制御を得ることができます。

採用問題の乱択アルゴリズムでは、紹介所から \(n\) 人分の候補者のリストを事前に受け取り、面接を行う前に、そのリストをランダムに並ベ替えます(一様ランダム順列を生成します)。そして、そのランダム化された順序で、決定的な手続きHIRE-ASSISTANTを実行します。

このように、アルゴリズム自身が乱数発生器を用いてランダムな選択(リストの順列化)を行うアルゴリズムを乱択アルゴリズムと呼びます。乱択アルゴリズムの性能を分析する際には、乱数発生器によって返される値の分布にわたる性能の期待値をとります。これを期待実行時間と呼びます。 RANDOMIZED-HIRE-ASSISTANTの期待される採用コストは、入力の順序がランダムであると仮定した場合のHIRE-ASSISTANTの平均ケース採用コストと等 しくなります。つまり、任意の入力に対して、期待される採用コストは \(O\left(c_h \ln n\right)\) となります。最悪の入力(能力の高い順に並んだリスト)が与えられても、ランダムな順列化によってその影響は打ち消され、期待されるコストは抑えられます。

つまり、分布を仮定する代わりに、無理やりある分布を押し付けるのです。

確率的解析と乱択アルゴリズムの対比

採用問題を例にとると、この2つのアプローチの違いが明確になります。

  • 確率的解析(決定的なHIRE-ASSISTANT + ランダムな入力の仮定): 入力が自然にランダムである場合に、そのアルゴリズムの平均的な性能を分析します。もし入力がランダムでない(意図的に操作された)場合、分析結果は適用できません。
  • 乱択アルゴリズム(RANDOMIZED-HIRE-ASSISTANT + 任意の入力): 入力がランダムであるかどうかにかかわらず、アルゴリズム自身がランダム性を導入することで、期待される性能を保証します。最悪ケースの入力によって性能が極端に悪化する可能性を、期待値として回避できます。

どちらの手法も、ランダム性が効率的なアルゴリズム設計や解析に貢献することを示しています。

配列のランダムな順列化

乱択アルゴリズムでは、しばしば入力配列をランダムに並び替える(順列化する)操作が必要になります。例えば、Quick Selectでランダムなピボットを選ぶ簡単な方法は、配列をランダムに並べ替えてから常に最初の要素をピボットに選ぶ、というものです。また、採用問題で、職業紹介所が候補者をランダムな順序で送ってれる保証がない場合に、自分で候補者のリストをランダムに並べ替えるというランダム化戦略RANDAMIZED-HIRE-ASSISTANTを考えました。この手続きRANDOMIZED-HIRE-ASSISTANTは、候補者のリストをランダムで順列化した後、決定的なHIRE-ASSISTANT手続きを実行するだけです。これにより、候補者がランダムな順序で提示された場合のパフォーマンス \(O\left(c_h \ln n\right)\)の平均ケースの採用コストと同一の期待される採用コスト \(O\left(c_h \ln n\right)\)を、あらゆる入力に対して保証できるようになります。

では、どのようにして配列を「一様ランダム順列」に並べ替えることが出来るでしょうか?「一様ランダム順列」とは、考えられる\(n!\)通りの順列のどれもが等しい確率で生成されるような順列です。

RANDOMLY-PERMUTE 手続き

以下の手続き RANDOMLY-PERMUTE は、\(n\) 個の要素を持つ配列 Aを、追加の記憶領域をほとんど使わずに(インプレースで)、一様ランダム順列に並べ替えることができます。配列の要素は 1 から \(n\) まで番号が振られているとします(プログラミングでは 0 から始まることも多いですが、ここでは 1 から始めます)。

この手続きは、i を 1 から \(n\) まで変化させながら繰り返します。i 番目の繰り返しでは、配列の A[i]という要素と、A[i] 自身を含むそれ以降の要素 A[i], A[i+1], ..., A[n] の中から、ランダムに選ばれた位置にある要素を交換します。

例えば、\(n=3\) の配列 A = [10, 20, 30] で考えてみましょう。

手続きが終了したとき、配列 A はランダムに並べ替えられています。しかし、この並べ替えが本当に「一様ランダム順列」になっていることを、数学的に保証する必要があります。

補題 :RANDOMLY-PERMUTE の正しさ

この手続きの正しさを示すために、以下の補題を証明しましょう。

補題

手続き RANDOMLY-PERMUTE は、一様なランダム順列を計算します。

この証明には、「ループ不変式」という強力な手法を用います。ループ不変式とは、ループが開始される直前、各繰り返しが開始される直前、そしてループが終了した直後に成り立つ性質のことです。この性質がループの各繰り返しで保たれる(維持される)ことを示すことで、ループ終了時の状態について結論を導き出します。

証明を進める前に、証明で使われる「k-順列」という言葉の意味を確認しましょう。

 k-順列とは?

\(n\) 個の要素からなる集合があるとします。この集合から \(k\) 個の要素を選び、それらを順序をつけて並べたものをk-順列 (k-permutation) と呼びます。例えば、集合\( \{a, b, c, d\} \)(\(n=4\)) の 2-順列 (\(k=2\)) は、以下の \(4 \times 3 = 12\) 通りです。
\((a, b), (a, c), (a, d)\)
\((b, a), (b, c), (b, d)\)
\((c, a), (c, b), (c, d)\)
\((d, a), (d, b), (d, c)\)

\(n\) 個の要素から \(k\) 個を選んで順序をつける方法は、 1 番目に \(n\) 通り、 2 番目に残りの \(n-1\) 通り、 \(\ldots 、 k\) 番目に残りの \(n-k+1\) 通りありますから、 k -順列の総数は \(n \times(n-1) \times \cdots \times(n-k+1)\) となります。これは順列の記号 \(P(n, k)\) または \({ }_n P_k\) を用いて \(n!/(n-k)!\) と書かれます。
\(n\)-順列は、集合の全ての要素を順序をつけて並べたものです。これが単に「順列」と呼ばれるものです。 \(n\) 個の要素の順列は \(n!\) 通りあります。私たちが最終的に生成したい「一様ランダム順列」とは、この \(n!\) 通りの \(n\)-順列のどれもが等しい確率 \(1 / n!\) で生成される状態のことです。

証明

さあ、RANDOMLY-PERMUTE 手続きが、一様ランダム順列を計算することを示す証明を、ループ不変式を使って進めていきましょう。

ループ不変式

for ループの i 番目のイテレーション(i が 1 から \(n\) まで変化)の直前において、元の配列に含まれていた \(n\) 個の要素のそれぞれの可能な\((i-1)\)-順列について、サブ配列 \(\mathrm{A}[1: \mathrm{i}-1]\) がこの\((i-1)\)-順列を確率 \((n-i+1)!/ n!\) で含んでいる。

この不変式の意味するところを、言葉で説明します。 ループが i 番目の繰り返しを始める直前には、配列の最初の \(\mathrm{i}-1\) 個の位置(A[1]から A[i-1])に、元の配列の要素が何らかの順序で配置されています。不変式は、「考えられる全ての\((i-1)\)-順列(つまり、元の \(n\) 個の要素から \(i-1\) 個を選んで並べたもの全て)について、実際に \(\mathrm{A}[1]\) から \(\mathrm{A}[\mathrm{i}-1]\) にその\((i-1)\)-順列が配置されている確率は、全て等しく \((n-i+1)!/ n!\) である」と主張しています。

なぜ確率が \((n-i+1)!/ n!\) という形なのでしょう?元の \(n\) 個の要素を全て並べた \(n!\) 通りの順列全体を考えます。その中で、最初の \(i-1\) 個の位置に特定の \((i-1)\)-順列 \(\left(\mathrm{x}_1, \ldots, \mathrm{x}_{\mathrm{i}-1}\right)\) が現れる順列は、残りの \(n-(i-1)=n-i+1\) 個の要素を後ろの \(n-i+1\) 個の位置にどのように並べてもよいので、 \((n-i+1)!\) 通りあります。もし最初から配列の要素がランダムな順序で並んでいたなら、特定の \((i-1)\)-順列が最初の \(i-1\) 個の位置に現れる確率は \((n-i+1)!/ n!\) となります。不変式は、ループの各繰り返しが始まる時点で、最初の \(i-1\) 個の要素が、この「ランダムな並び替え」で期待される確率 と同じ確率で、あらゆる \((i-1)\)-順列になっていることを主張しているのです。

この不変式が正しいことを、以下の3つのステップで示します。

1.初期化

ループが開始される直前( \(\mathrm{i}=1\) の直前)に不変式が成り立つことを示します。
\(\mathrm{i}=1\) のとき、不変式はサブ配列 \(\mathrm{A}[1: 1-1]=\mathrm{A}[1: 0]\)(これは空の配列)が、考えられる全ての \((1-1)-\) 順列 \(=0-\) 順列(これは要素が 0 個の順列 で、 1 つだけ存在する)を、確率 \((n-1+1)!/ n!=n!/ n!=1\) で含んでいる、と主張します。
空の配列は、要素が 0 個の 0 -順列を確かに含んでいます。そして、それが起こる確率は 1 です。したがって、不変式はループが開始される直前に成り立 ちます。

2.維持

i 番目のイテレーションの直前で不変式が成り立っていると仮定し、i 番目のイテレーションが完了した後(すなわち i+ 1 番目のイテレーションの直前)でも不変式が成り立つことを示します。(数学的帰納法のようなイメージ)
つまり、サブ配列 \(\mathrm{A}[1: \mathrm{i}]\) が、考えられる全ての \(\mathrm{i}-\) 順列を確率 \((n-i)!/ n!\) で含んでいることを示せばよいのです。( i が \(\mathrm{i}+1\) に増えることで、不変式の \((n-(i+1)+1)!/ n!=(n-i)!/ n!\) という形になるため。)

特定の \(\mathrm{i}-\) 順列 \(\left(x_1, x_2, \ldots, x_i\right)\) を考えます。この \(\mathrm{i}-\) 順列が \(\mathrm{A}[1: \mathrm{i}]\) に現れる確率はいくらでしようか?
この i-順列が現れるためには、以下の2つのイベントが連続して起こる必要があります。

  • イベント \(\mathrm{E}_1\) :i 番目のイテレーションの直前で、サブ配列 \(\mathrm{A}[1: \mathrm{i}-1]\) が、この \(\mathrm{i}-\) 順列の最初の \((\mathrm{i}-1)\)-要素である \(\left(x_1, \ldots, x_{i-1}\right)\) という ( \(\mathrm{i}-1\) )-順列になっている。
  • イベント \(E_2\) :i 番目のイテレーションにおいて、要素 \(x_i\) が \(\mathrm{A}[i]\)の位置に置かれる。(手続きでは交換によって起こります。)

求めたい確率は、E₁ と E₂ が両方とも起こる確率 \(Pr\{E_1 \cap E_2\}\) です。条件付き確率の定義により、
$$Pr\{E_1 \cap E_2\} = Pr\{E_2 \mid E_1\} \times Pr\{E_1\}$$

\(Pr\{E_1\}\) は、不変式の仮定から分かります。i 番目のイテレーションの直前では不変式が成り立っているので、サブ配列 A[1: i - 1] が特定の (i - 1)-順列 \((x_1, \ldots, x_{i-1})\) である確率は、\((n - i + 1)! / n!\) です。
$$Pr\{E_1\} = \frac{(n - i + 1)!}{n!}$$

\(Pr\left\{E_2 \mid E_1\right\}\) を計算します。イベント \(\mathrm{E}_1\) が起こった、つまり \(\mathrm{A}[1: \mathrm{i}-1]\) は \(\left(x_1, \ldots, x_{i-1}\right)\) という特定の( \(\mathrm{i}-1\) )-順列になった、という条件下で考えます。
\(i\) 番目のイテレーションでは、 \(A[i]\) と \(A[R A N D O M(i, n)]\) が交換されます。 \(A[R A N D O M(i, n)]\) は、 \(A[i]\) から \(A[n]\) までの \(n-i+1\) 個の要素の中 から、ランダムに(確率 \(1 /(n-i+1)\) で)選ばれた位置です。
イベント \(\mathrm{E}_1\) が起こった後、配列 \(\mathrm{A}\)は現在の要素( \(\mathrm{A}[1 . . \mathrm{i}-1]\) )と残りの要素( \(\mathrm{A}[\mathrm{i} . . \mathrm{n}]\) )に分かれています。特に、 \(\mathrm{A}[1 . . \mathrm{i}-1]\) は \(\left(x_1, \ldots, x_{i-1}\right)\) です。そして、元の配列に含まれていた残りの \(n-(i-1)=n-i+1\) 個の要素が \(\mathrm{A}[\mathrm{i} . . \mathrm{n}]\) に入っています。

\(\mathrm{A}[1..\mathrm{i}]\)が最終的に \(\left(x_1, \ldots, x_i\right)\) という i-順列になるためには、目的の要素 \(x_i\) が、i 番目のイテレーションの開始時点( \(\mathrm{E}_1\) が起こった後)でサブ配列 \(\mathrm{A}[\mathrm{i}: \mathrm{n}]\) のどこかに存在している必要があります。もし \(x_i\)が \(\mathrm{A}[1: \mathrm{i}-1]\) に含まれてしまっていたら(つまり、もし \(x_i\)が \(\left\{x_1, \ldots, x_{i-1}\right\}\) の中にあったら)、A[1:i]が\((x_1. \ldots, x_i)\)となることはあり得ません(異なる要素からなる順列を考えているため)。
したがって、イベント \(\mathrm{E}_1\) が起こったという条件下で、\(x_i\)は必ず \(\mathrm{A}[\mathrm{i}: \mathrm{n}]\) の中に含まれています(そうでないと、A[1:i]が\((x_1. \ldots, x_i)\)になり得ないため)。
i 番目のイテレーションでは、A[RANDOM(i,n)]によって、A[i:n]の中の \(n-i+1\) 個の位置のいずれかが等確率で選ばれます。目的の要素 \(x_i\)が入っているその特定の1つの位置が選ばれる確率は、 \(1 /(n-i+1)\) です。これが、A[i]に \(x_i\)が置かれる確率、つまり \(Pr\left\{E_2 \mid E_1\right\}\) です。
$$Pr\{E_2 \mid E_1\} = \frac{1}{n - i + 1}$$

最後に、\(Pr\{E_1 \cap E_2\}\) を計算します。
$$Pr\{E_1 \cap E_2\} = Pr\{E_2 \mid E_1\} \times Pr\{E_1\} = \frac{1}{n - i + 1} \times \frac{(n - i + 1)!}{n!} = \frac{1}{n - i + 1} \times \frac{(n - i + 1) \times (n - i)!}{n!} = \frac{(n - i)!}{n!}$$
これは、サブ配列 \(\mathrm{A}[1: \mathrm{i}]\) が特定の \(\mathrm{i}-\) 順列 \(\left(x_1, \ldots, x_i\right)\) である確率が \((n-i)!/ n!\) であることを示しています。 この結果は、i+1 番目のイテレーションの直前に不変式が主張する確率の形と一致します。したがって、ループ不変式は維持されます。

3.終了

ループはi が 1 から \(n\) まで変化するので、正確に \(n\) 回繰り返して終了します。ループが終了したとき、iの値は \(n+1\) になります。 このとき、不変式はサブ配列 \(\mathrm{A}[1: ~ \mathrm{n}+1-1]=\mathrm{A}[1: \mathrm{n}] \quad\)(これは配列全体)が、考えられる全ての \((\mathrm{n}+1-1)-\) 順列 \(=n-\) 順列(つまり、配列全体を並 べ替えたもの)を、確率 \((n-(n+1)+1)!/ n!=0!/ n!=1 / n!\) で含んでいる、と主張します。 \(0!=1\) なので、この確率は \(1 / n!\) です。
\(0! = 1\) なので、この確率は \(1/n!\) です。

これは、配列 A の全ての要素からなる任意の特定の \(n\)-順列が、確率 \(1/n!\) で生成されることを意味します。これはまさに「一様ランダム順列」の定義です!

証明の3つのステップ全てが完了したため、手続き RANDOMLY-PERMUTE は一様ランダム順列を計算することが数学的に保証されました。□

なぜ RANDM(i, n) なのか?

ここまでで、配列を一様ランダム順列にする手続き RANDOMLY-PERMUTE を紹介しました。これは swap A[i] with A[RANDOM(i, n)] という交換を i を 1 から n まで繰り返すものでした。この手続きが一様ランダム順列を生成することは、ループ不変式を使って証明しました。

ここでは、似ているけれども一様ランダム順列を生成できない失敗する手続きを見て、なぜ RANDOMLY-PERMUTEの設計が重要なのかをさらに深く理解します。

この手続きが、一様ランダム順列を生成しないことを示しましょう。考えられる全ての \(n!\) 通りの順列が、どれも等しい確率 \(1 / n!\) で生成されるならば、一様ランダム順列です。しかし、PERMUTE- WITH-ALL ではそうなりません。

n=3 の場合で検証

要素が 3 つの配列 \(A=[1,2,3]\) を考えます。考えられる順列は \(3!=6\) 通りです:\([1,2,3]\) ,\([1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]\) 。一様ランダムであれば、それぞれの順列が生成される確率は \(1 / 6\) になるはずです。

PERMUTE-WITH-ALL を実行すると、i が \(1,2,3\) と変化します。各ステップで RANDOM(1,3)が呼 ばれ、これは \(1,2,3\) のいずれかを確率 \(1 / 3\) で返します。全部で 3 ステップあり、各ステップが独立なので、考えられるランダムな選択のシーケンス(例えば「ステップ1でRANDOMが1、ステッ プ2でRANDOMが2、ステップ3でRANDOMが1」のような組み合わせ)は \(3 \times 3 \times 3=27\) 通りあり ます。これらの 27 通りのシーケンスは、それぞれが等しい確率 \(1 / 27\) で発生します。

各ランダムな選択のシーケンスが、最終的にどの順列を生成するかを追跡してみましょう。元の配列を \([1,2,3]\) とします。

上記の追跡(または正確な計算)によると、各最終順列が生成される確率は以下のようになります。

$$
\begin{aligned}
& {[1,2,3]: 5 \text { 回 }\left(k_1=1, k_2=2, k_3=3 ; k_1=1, k_2=3, k_3=2 ; k_1=2, k_2=1, k_3=3 ;\right.} \\
& \left.k_1=2, k_2=3, k_3=1 ; k_1=3, k_2=1, k_3=2 ; k_1=3, k_2=2, k_3=1\right) \\
& [1,3,2]: 4 \text { 回 } \\
& [2,1,3]: 4 \text { 回 } \\
& [2,3,1]: 4 \text { 回 } \\
& [3,1,2]: 5 \text { 回 } \\
& [3,2,1]: 5 \text { 回 }
\end{aligned}
$$

したがって、各順列が生成される確率は以下の通りです(合計 27):

$$
\begin{aligned}
& \Pr\{[1,2,3]\}=5 / 27 \\
& Pr\{[1,3,2]\}=4 / 27 \\
&Pr\{[2,1,3]\}=4 / 27 \\
& Pr\{[2,3,1]\}=4 / 27 \\
& Pr\{[3,1,2]\}=5 / 27 \\
& Pr\{[3,2,1]\}=5 / 27
\end{aligned}
$$

これらの確率は全て等しいわけではありません(例えば \(5 / 27 \neq 1 / 6\) )。したがって、PERMUTE- WITH-ALL は一様ランダム順列を生成しません。□

 

ランダムな入力とは?

多くの競技プログラミングの問題では、「制約を満たすどんな入力ケースでも正解すること」が求められます。これは、アルゴリズムが考えうる最も意地悪な入力(最悪ケース)に対しても効率的に動作する必要があることを意味します。先の数当てゲームで、決定的な順番で質問する戦略が意地悪な入力に弱いことを見たのは、この考え方に基づいています。

一方で、現実世界で遭遇する問題やデータは、必ずしもアルゴリズムの弱点を突くように巧妙に作られているわけではありません。多くの場合、データは何らかの自然なプロセスやランダムな要因によって生成され、「偏りがない」または特定の確率分布に従うという性質を持つことがあります。このような入力を「ランダムな入力(random input)」と呼びます。

「一般のデータ」と「ランダムなデータ」はどう違うでしょうか?一般のデータには、特定のパターンに集中していたり(偏っていたり)、アルゴリズムにとって扱いにくように特別に作られた「意地悪なデータ」が含まれる可能性があります。一方、「ランダムなデータ」は、通常、データの分布に大きな偏りがありません。

この「偏りがない」という性質を利用することで、決定的なアルゴリズムであっても、ランダムな入力に対しては非常に効率的に問題を解ける場合があります。このような解析手法を確率的解析(Probablisitic Analysis)と呼びます。ここでは、アルゴリズムは決定的ですが、そのパフォーマンスを入力の確率分布に基づいて解析します。

 

指示確率変数

確率的解析を進めるうえで非常に便利なツールが指示確率変数 (Indicator Random Variable) です。

サンプル空間 \(S\) とその中の事象 \(A\) が与えられたとき、事象 \(A\) に関連付けられた指示確率変数 \(I\{A\}\) は、次のように定義されます。

$$
I\{A\}= \begin{cases}1 & (\text { 事象 } A \text { が発生する場合 }) \\ 0 & (\text { 事象 } A \text { が発生しない場合 })\end{cases}
$$

確率変数の最も重要な性質は、その期待値が事象が発生する確率に等しいことです。

補題

サンプル空間 \(S\) とサンプル空間 \(S\) 内の事象 \(A\) が与えられたとき、 \(X_A=I\{A\}\) とします。このとき、 \(E\left[X_A\right]=\operatorname{Pr}\{A\}\) です。

証明

指示確率変数と期待値の定義によれば、確率変数 \(X_A\) が取りうる値は1(事象 \(A\) が発生する場合)と0(事象 \(A\) が発生しない場合)の2つだけです。事象 \(A\) が発生する確率は \(\operatorname{Pr}\{A\}\) 、発生しない確率(余事象 \(\bar{A}\) が発生する確率)は \(\operatorname{Pr}\{\bar{A}\}=1-\operatorname{Pr}\{A\}\) です。期待値の定義(確率変数が取りうる値とそ の確率の積の総和)より、

$$
E\left[X_A\right]=1 \cdot \operatorname{Pr}\{A\}+0 \cdot \operatorname{Pr}\{\bar{A}\}=\operatorname{Pr}\{A\}+0=\operatorname{Pr}\{A\}
$$

したがって、 \(E\left[X_A\right]=\operatorname{Pr}\{A\}\) です。□

指示確率変数は、複数の事象が関わる状況で期待値を計算する際に特に役立ちます。これは期待値の線形性(Linearity of Expectation)と組み合わせることで強力な手法となります。期待値の線形性とは、「確率変数の和の期待値は、個々の確率変数の期待値の和に等しい」という性質です。

$$
E\left[X_1+X_2+\cdots+X_n\right]=E\left[X_1\right]+E\left[X_2\right]+\cdots+E\left[X_n\right] $$

この性質の素晴らしい点は、確率変数\(X_1, \ldots, X_n\) が互いに独立している必要がないという点です。どんな場合でも成り立ちます。

例として、公正なコインを \(n\) 回投げたときに表が出る回数の期待値を計算してみましょう
\(i\) 番目の投げが表になる事象を \(H_i\) とします。 \(i\) 番目の投げが表になるかどうかを示す指示確率変数 \(X_i=I\left\{H_i\right\}\) を定義します。
\(n\) 回の投げで表が出た合計回数を表す確率変数を \(X\) とすると、 \(X=\sum_{i-1}^n X_i\) と書けます。
期待値の線形性より、 \(E[X]=E\left[\sum_{i-1}^n X_i\right]=\sum_{i-1}^n E\left[X_i\right]\) です。
公正なコインの場合、 \(i\) 番目の投げが表になる確率 \(\operatorname{Pr}\left\{H_i\right\}=1 / 2\) なので、指示確率変数の期待値は \(E\left[X_i\right]=\operatorname{Pr}\left\{H_i\right\}=1 / 2\) です。
したがって、期待される表の回数は \(E[X]=\sum_{i-1}^n 1 / 2=n \times(1 / 2)=n / 2\) となります。これは直感的にも分かりやすい結果ですが、指示確率変数を使うと非常に簡潔に導出できます。

採用問題の確率的解析

先ほど触れた採用問題(新しいオフィスアシスタントを雇う問題)に戻りましょう。この問題を確率的解析の観点から見てみます。決定的な手続き HIRE-ASSISTANT を使用しますが、入力(候補者が到着する順序)がランダムであると仮定します。具体的には、n人の候補者の能力には全順序があり、到着する順序は能力のランクの一様ランダム順列であると仮定します。

新しいオフィスアシスタントを雇う回数 X の期待値を計算します。
\(i\) 番目の候補者が雇われる事象に関連付けられた指示確率変数 \(X_i=I\{\) 候補者iが雇われた \(\}\) を定義します。
雇われる合計回数 \(X=\sum_{i-1}^n X_i\) です。
期待値の線形性により、 \(E[X]=\sum_{i-1}^n E\left[X_i\right]\) です。
補題より、 \(E\left[X_i\right]=\operatorname{Pr}\{\) 候補者iが雇われた \(\}\) です。
では、候補者 \(i\) が雇われる確率 \(\operatorname{Pr}\{\) 候補者iが雇われた \(\}\) はいくつでしょうか?HIRE-ASSISTANTの手続きでは、候補者 \(i\) は、それまでに面接した候補者 \(1,2, \ldots, i-1\) の誰よりも優秀である場合に限り雇われます。候補者がランダムな順序で到着すると仮定したため、最初の \(i\) 人の候補者(候補者 1 か ら \(i\) まで)はランダムな順序で現れています。これら最初の \(i\) 人の中で最も優秀な候補者が、候補者 \(i\) である確率はいくらでしょうか?最初の \(i\) 人の候補者のうち、誰が最も優秀である可能性も等しく高いです。したがって、候補者 \(i\) が最初の \(i\) 人の中で最も優秀である確率は \(1 / i\) です。そして、候補者 \(i\) が雇われるのは、候補者 \(i\) が最初の \(i\) 人の中で最も優秀である場合に限ります。
したがって、 \(\operatorname{Pr}\{\) 候補者iが雇われた \(\}=1 / i\) です

雇われる回数の期待値は、

$$
E[X]=\sum_{i=1}^n E\left[X_i\right]=\sum_{i=1}^n \frac{1}{i}
$$

これは調和級数(Harmonic Series)と呼ばれ、 \(H_n\) と表記されます。調和級数は自然対数を用いて近似できます

$$
H_n=\sum_{i-1}^n \frac{1}{i}=\ln n+O(1)
$$

証明

自然数 \(n\) に対する**調和級数 (Harmonic Series)** \(H_n\) は、以下のように定義されます。
\[
H_n = \sum_{i=1}^n \frac{1}{i} = 1 + \frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n}
\] この調和級数は、\(n \to \infty\) のときに発散します。そして、その増加の度合いは自然対数 \(\ln n\) と密接に関係しており、差が定数に収束することが知られています。その関係式は以下の通りです。
\[
\sum_{i=1}^n \frac{1}{i} = \ln n + O(1)
\] ここで \(O(1)\) は、\(n \to \infty\) のときに有界となる項を表します。つまり、調和級数と \(\ln n\) の差 \(\sum_{i=1}^n \frac{1}{i} - \ln n\) は、\(n \to \infty\) のときに何らかの定数(オイラー・マスケローニ定数 \(\gamma \approx 0.57721\))に収束します。

この関係を厳密に証明するために、積分の考え方を用います。関数 \(f(x) = 1/x\) を考えます。この関数は \(x > 0\) で正、単調減少です。

シグマ \(\sum_{i=1}^n \frac{1}{i}\) は、長方形の面積の合計と見なすことができます。区間 \([i, i+1]\) 上で高さ \(1/i\) の長方形(左端での関数の値を取る)を考えると、その面積は \(1/i \times (i+1 - i) = 1/i\) です。これを \(i=1\) から \(n\) まで合計すると、\(\sum_{i=1}^n \frac{1}{i}\) となります。これは、関数 \(f(x) = 1/x\) のグラフよりも**上**に位置する長方形の面積の合計です。

一方、\(i=1\) から \(n\) までの定積分 \(\int_1^n \frac{1}{x} dx\) は、関数 \(f(x) = 1/x\) のグラフの下の面積を表します。
\[
\int_1^n \frac{1}{x} dx = [\ln |x|]_1^n = \ln n - \ln 1 = \ln n
\]

さて、\(f(x) = 1/x\) が単調減少関数であることを利用すると、以下の不等式が成り立ちます。

区間 \([i, i+1]\) において、
- 左端の高さ \(1/i\) を持つ長方形の面積は \(1/i\) です。これは、この区間での積分の値 \(\int_i^{i+1} \frac{1}{x} dx\) よりも**大きい**です(関数が減少しているため)。
\[
\frac{1}{i} \ge \int_i^{i+1} \frac{1}{x} dx \quad \text{for } i \ge 1
\] - 右端の高さ \(1/(i+1)\) を持つ長方形の面積は \(1/(i+1)\) です。これは、この区間での積分の値 \(\int_i^{i+1} \frac{1}{x} dx\) よりも**小さい**です(関数が減少しているため)。
\[
\frac{1}{i+1} \le \int_i^{i+1} \frac{1}{x} dx \quad \text{for } i \ge 1
\]

これらの不等式を \(i=1\) から \(n-1\) まで(または \(n\) まで)合計してみましょう。

まず、\(1/i \ge \int_i^{i+1} \frac{1}{x} dx\) の不等式を \(i=1\) から \(n-1\) まで合計します。
\[
\sum_{i=1}^{n-1} \frac{1}{i} \ge \sum_{i=1}^{n-1} \int_i^{i+1} \frac{1}{x} dx
\] 和記号と積分記号は交換できます(積分の線形性)。また、連続する区間での積分の合計は、大きな区間での積分になります。
\[
\sum_{i=1}^{n-1} \int_i^{i+1} \frac{1}{x} dx = \int_1^2 \frac{1}{x} dx + \int_2^3 \frac{1}{x} dx + \cdots + \int_{n-1}^n \frac{1}{x} dx = \int_1^n \frac{1}{x} dx = \ln n
\] したがって、
\[
\sum_{i=1}^{n-1} \frac{1}{i} \ge \ln n
\] この和に最後の項 \(1/n\) を加えると、
\[
\sum_{i=1}^n \frac{1}{i} = \left( \sum_{i=1}^{n-1} \frac{1}{i} \right) + \frac{1}{n} \ge \ln n + \frac{1}{n}
\] これは、\(\sum_{i=1}^n \frac{1}{i}\) が \(\ln n\) より大きいこと(そして \(\ln n + 1/n\) より大きいこと)を示しています。

次に、\(1/(i+1) \le \int_i^{i+1} \frac{1}{x} dx\) の不等式を \(i=1\) から \(n-1\) まで合計します。
\[
\sum_{i=1}^{n-1} \frac{1}{i+1} \le \sum_{i=1}^{n-1} \int_i^{i+1} \frac{1}{x} dx = \int_1^n \frac{1}{x} dx = \ln n
\] 和 \(\sum_{i=1}^{n-1} \frac{1}{i+1}\) は、\(i\) を \(j-1\) に置き換えると \(\sum_{j=2}^n \frac{1}{j}\) となります。これは調和級数 \(H_n\) から最初の項 \(1/1=1\) を除いたものです。
\[
\sum_{i=1}^{n-1} \frac{1}{i+1} = \frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n} = \left( \sum_{i=1}^n \frac{1}{i} \right) - 1 = H_n - 1
\] したがって、
\[
H_n - 1 \le \ln n
\] \[
H_n \le \ln n + 1
\] これは、\(\sum_{i=1}^n \frac{1}{i}\) が \(\ln n + 1\) 以下であることを示しています。

これまでの結果をまとめると、以下の不等式が得られました。
\[
\ln n + \frac{1}{n} \le \sum_{i=1}^n \frac{1}{i} \le \ln n + 1
\] \[
\frac{1}{n} \le \sum_{i=1}^n \frac{1}{i} - \ln n \le 1
\] この不等式は、差 \(\sum_{i=1}^n \frac{1}{i} - \ln n\) が、\(n \ge 1\) のとき常に 0 より大きく 1 以下であることを示しています。つまり、この差は \(n \to \infty\) のときに**有界である**ことが分かりました。

さらに進んで、差 \(\sum_{i=1}^n \frac{1}{i} - \ln n\) が収束すること、すなわち \(O(1)\) の項が定数に収束することを示すこともできます。これには、各区間 \([i, i+1]\) における長方形の面積と積分の差を考えます。

\(i \ge 1\) に対して、長方形の面積 \(1/i\) と積分 \(\int_i^{i+1} \frac{1}{x} dx\) の差を \(d_i\) とします。
\[
d_i = \frac{1}{i} - \int_i^{i+1} \frac{1}{x} dx
\] \(f(x)=1/x\) は凸関数でもあるため、\(d_i > 0\) です。
調和級数と積分の差を考えると、
\[
\sum_{i=1}^n \frac{1}{i} - \int_1^n \frac{1}{x} dx = \left( \sum_{i=1}^{n-1} \frac{1}{i} - \int_1^n \frac{1}{x} dx \right) + \frac{1}{n}
\] \[
= \sum_{i=1}^{n-1} \frac{1}{i} - \sum_{i=1}^{n-1} \int_i^{i+1} \frac{1}{x} dx + \frac{1}{n} = \sum_{i=1}^{n-1} \left( \frac{1}{i} - \int_i^{i+1} \frac{1}{x} dx \right) + \frac{1}{n} = \sum_{i=1}^{n-1} d_i + \frac{1}{n}
\] または、
\[
\sum_{i=1}^n \frac{1}{i} - \ln n = \sum_{i=1}^n \left( \frac{1}{i} - \int_i^{i+1} \frac{1}{x} dx \right) + \int_n^{n+1} \frac{1}{x} dx - \int_1^n \frac{1}{x} dx + \ln n
\] \[
\sum_{i=1}^n \frac{1}{i} - \ln n = \sum_{i=1}^n \left( \frac{1}{i} - \int_i^{i+1} \frac{1}{x} dx \right) + \int_n^{n+1} \frac{1}{x} dx - (\ln n) + \ln n
\] 少し整理を変えます。
\[
\sum_{i=1}^n \frac{1}{i} - \ln n = \sum_{i=1}^n \frac{1}{i} - \int_1^n \frac{1}{x} dx = \sum_{i=1}^{n-1} \frac{1}{i} + \frac{1}{n} - \int_1^n \frac{1}{x} dx
\] \[
= \sum_{i=1}^{n-1} \left( \frac{1}{i} - \int_i^{i+1} \frac{1}{x} dx \right) + \frac{1}{n} + \sum_{i=1}^{n-1} \int_i^{i+1} \frac{1}{x} dx - \int_1^n \frac{1}{x} dx
\] \[
= \sum_{i=1}^{n-1} d_i + \frac{1}{n} + \int_1^n \frac{1}{x} dx - \int_1^n \frac{1}{x} dx = \sum_{i=1}^{n-1} d_i + \frac{1}{n}
\] 差 \(d_i = \frac{1}{i} - \int_i^{i+1} \frac{1}{x} dx\) は、区間 \([i, i+1]\) における \(1/x\) のグラフ上の面積と高さ \(1/i\) の長方形の面積との差です。この差 \(d_i\) は、\(i \to \infty\) のときに \(O(1/i^2)\) のオーダーで減少することが示せます(テイラー展開などを用います)。
例えば、\( \int_i^{i+1} \frac{1}{x} dx = \ln(i+1) - \ln i = \ln(1 + 1/i) \approx 1/i - 1/(2i^2) + O(1/i^3) \) ( \(x \approx 0\) で \( \ln(1+x) \approx x - x^2/2 \))。
したがって、\( d_i = \frac{1}{i} - (\frac{1}{i} - \frac{1}{2i^2} + O(1/i^3)) = \frac{1}{2i^2} + O(1/i^3) \) となり、\(d_i\) は正で、\(i \to \infty\) のときに \(O(1/i^2)\) の速さで 0 に収束します。
級数 \(\sum_{i=1}^\infty d_i\) は、\( \sum_{i=1}^\infty 1/i^2 \) が収束する(例えば \(\pi^2/6\) に収束)ことから、収束することが分かります。
つまり、\(\sum_{i=1}^\infty d_i = D\) という有限の値に収束します。
したがって、
\[
\sum_{i=1}^n \frac{1}{i} - \ln n = \sum_{i=1}^{n-1} d_i + \frac{1}{n} = \left( \sum_{i=1}^\infty d_i \right) - \left( \sum_{i=n}^\infty d_i \right) + \frac{1}{n} = D - \left( \sum_{i=n}^\infty d_i \right) + \frac{1}{n}
\] ここで、\( \sum_{i=n}^\infty d_i \) は \(n \to \infty\) のときに 0 に収束する項です。実際、\(d_i = O(1/i^2)\) なので、\( \sum_{i=n}^\infty d_i = O(\sum_{i=n}^\infty 1/i^2) = O(1/n) \) です。また、\(1/n\) も \(n \to \infty\) のときに 0 に収束する項です。
したがって、
\[
\sum_{i=1}^n \frac{1}{i} - \ln n = D + O(1/n)
\] この \(D\) がオイラー・マスケローニ定数 \(\gamma\) です。\(O(1/n)\) は \(n \to \infty\) のときに 0 に収束するので、有界です。したがって、\(O(1)\) に含まれます。

以上の議論から、
\[
\sum_{i=1}^n \frac{1}{i} = \ln n + \gamma + O(1/n)
\] というより精密な式が成り立ち、これから \(\sum_{i=1}^n \frac{1}{i} = \ln n + O(1)\) が厳密に導かれます。\(O(1)\) は、\( \gamma + O(1/n) \) という項が \(n\) にかかわらず有界であることを意味します。実際、\(n \to \infty\) の極限では定数 \(\gamma\) に収束します。

最終的に、積分を用いた比較と、差分の級数の収束性を示すことで、調和級数と自然対数の間に差が定数に収束するという関係が厳密に証明されました。□

したがって、候補者がランダムな順序で提示されると仮定すると、平均的には約 \(\ln n\) 人しか雇いません。面接コストを \(c_i\) 、採用コストを \(c_h\) とすると、総 コストは \(O\left(c_i n+c_h m\right)\) であり、面接コスト \(c_i n\) は固定ですが、採用コスト \(c_h m\) は変動します。期待される採用回数 \(E[m]\) は \(E[X] \approx \ln n\) なので、平均ケースの総採用コストは \(O\left(c_h \ln n\right)\) となります。これは最悪ケースのコスト \(O\left(c_h n\right)\) に比べて大幅な改善です。

 

確率的解析と指示確率変数のさらなる応用

このセクションでは、確率的解析と指示確率変数を用いて、興味深いいくつかの確率問題を詳しく分析します。これらの問題は、一見簡単に見えるものから、直感に反する結果を示すものまで様々ですが、基本的な確率論と期待値の線形性というツールがいかに強力であるかを示してくれます。

誕生日のパラドックス (Birthday Paradox)

問題

部屋に \(k\) 人の人がいます。うるう年を無視し、1年は365日であるとし、誕生日は1年のどの日でも等確率に起こり、各人の誕生日は独立であると仮定します。

何人の人が集まれば、「少なくとも2人が同じ誕生日である」確率が50%を超えるでしょうか?

 

直感的には、365日もあるのだから、かなりの人数が集まらないと誕生日が一致する確率は低そうに思えます。しかし、実際の結果は多くの人の予想を裏切ります。これが「パラドックス」と呼ばれる所以です(ただし、これは論理的なパラドックスではなく、直感とのずれによるものです)。

この問題を解くために、2つの異なるアプローチを考えます。

余事象の確率を計算する(厳密な方法)

「少なくとも2人が同じ誕生日である」という事象の確率は、「全員の誕生日が異なる」という事象の確率を1から引いたものです。この「全員の誕生日が異なる」確率を計算する方が簡単です。

\(k\) 人の人を順番に1番目の人、2番目の人、...、\(k\) 番目の人とします。
- 1番目の人の誕生日は、どの日でも構いません(365通り)。
- 2番目の人の誕生日が1番目の人と異なる確率は \((365 - 1) / 365\) です。
- 3番目の人の誕生日が1番目と2番目の人(異なる誕生日です)と異なる確率は \((365 - 2) / 365\) です。
- ...
- \(i\) 番目の人の誕生日が、それ以前の \(i-1\) 人全員(異なる誕生日です)と異なる確率は \((365 - (i-1)) / 365\) です。

全員の誕生日が異なる確率は、これらの確率を全て掛け合わせたものです。これを \(Pr\{\text{全員異なる}\}\) と書くと、
$$
Pr\{\text{全員異なる}\} = \frac{365}{365} \times \frac{365-1}{365} \times \frac{365-2}{365} \times \cdots \times \frac{365-(k-1)}{365}
$$
$$
= 1 \times \left(1 - \frac{1}{365}\right) \times \left(1 - \frac{2}{365}\right) \times \cdots \times \left(1 - \frac{k-1}{365}\right) \quad \text{(テキストの式 5.8 と関連)}
$$
この式は、階乗を使って \(\frac{P(365, k)}{365^k} = \frac{365! / (365-k)!}{365^k}\) と書くこともできます。

求めたい確率「少なくとも2人が同じ誕生日である」は、
$$
Pr\{\text{少なくとも2人同じ}\} = 1 - Pr\{\text{全員異なる}\} = 1 - \prod_{i=1}^{k-1} \left(1 - \frac{i}{365}\right)
$$
この確率が0.5を超えるような最小の \(k\) を見つけたいのです。
$$
1 - \prod_{i=1}^{k-1} \left(1 - \frac{i}{365}\right) \ge 0.5
$$
$$
\prod_{i=1}^{k-1} \left(1 - \frac{i}{365}\right) \le 0.5
$$
この不等式を解くには、具体的な \(k\) の値を計算していくか、近似式を用いる必要があります。近似として、\(1+x \approx e^x\) (xが小さい場合) という関係から導かれる \(1-x \le e^{-x}\) という不等式を使います 。
$$
\prod_{i=1}^{k-1} \left(1 - \frac{i}{365}\right) \le \prod_{i=1}^{k-1} e^{-i/365} = e^{-\sum_{i=1}^{k-1} i/365} = e^{-k(k-1)/(2 \times 365)}
$$
したがって、\(e^{-k(k-1)/(2 \times 365)} \le 0.5\) となる \(k\) を探します。両辺の自然対数を取ると、
$$
-\frac{k(k-1)}{2 \times 365} \le \ln(0.5) = -\ln 2
$$
$$
\frac{k(k-1)}{730} \ge \ln 2
$$
$$
k(k-1) \ge 730 \times \ln 2 \approx 730 \times 0.693 \approx 505.89
$$
\(k(k-1)\) が約506以上になる最小の整数 \(k\) を探します。\(k^2 \approx 506\) とすると \(k \approx \sqrt{506} \approx 22.49\)。したがって、\(k=23\) のときにこの不等式を満たします。
正確な計算(または表の参照)によると、\(k=22\) のときの確率は約0.475、\(k=23\) のときの確率は約0.507となります。
**驚くべきことに、23人いれば、少なくとも2人が同じ誕生日である確率は50%を超えるのです。**

 

一致する誕生日のペア数の期待値を計算する(指示確率変数を用いた方法)

部屋にいる \(k\) 人の中から、任意の2人組(ペア)を選びます。ペアの総数は \(\binom{k}{2} = \frac{k(k-1)}{2}\) 通りあります。これらのペアそれぞれについて、「誕生日が一致するかどうか」という事象を考え、指示確率変数を使います。

\(k\) 人の人々を 1, 2, ..., \(k\) と番号付けします。
1 \(\le i < j \le k\) である任意のペア \((i, j)\) に対して、以下の指示確率変数 \(X_{i,j}\) を定義します。
\[
X_{i,j} = I\{ \text{人 } i \text{ と 人 } j \text{ の誕生日が同じである} \} = \begin{cases} 1 & \text{(一致する場合)} \\ 0 & \text{(一致しない場合)} \end{cases}
\] 補題5.1より、指示確率変数の期待値はその事象が起こる確率に等しいです。
\[
E[X_{i,j}] = Pr\{ \text{人 } i \text{ と 人 } j \text{ の誕生日が同じである} \}
\] 人 \(i\) と 人 \(j\) の誕生日が同じ日である確率はいくつでしょうか? 人 \(i\) の誕生日は365日中の特定の日であり、人 \(j\) の誕生日がその特定の日と同じである確率は \(1/365\) です(誕生日は独立に、365日全てが等確率であると仮定しているからです)。
したがって、\(E[X_{i,j}] = 1/365\) です。

部屋にいる全員の中で、誕生日が一致するペアの総数を確率変数\(X\) とします。これは、全ての可能なペアに対する指示確率変数の合計です。
\[
X = \sum_{1 \le i < j \le k} X_{i,j}
\] 誕生日が一致するペア数の期待値\(E[X]\) は、期待値の線形性を用いて、個々の指示確率変数の期待値の合計として求められます。期待値の線形性は、確率変数が独立でなくても成り立ちます。\(X_{i,j}\) と \(X_{i,l}\) は、どちらも 人 \(i\) が関わるため独立ではありませんが、合計の期待値は単純な和になります。
\[
E[X] = E\left[\sum_{1 \le i < j \le k} X_{i,j}\right] = \sum_{1 \le i < j \le k} E[X_{i,j}] \quad \text{(テキストの式 5.4.1 より)}
\] 全てのペア \((i, j)\) について \(E[X_{i,j}] = 1/365\) なので、
\[
E[X] = \sum_{1 \le i < j \le k} \frac{1}{365}
\] 和は、\(1 \le i < j \le k\) という条件を満たすペア \((i, j)\) の数に \(1/365\) を掛けたものです。ペアの総数は \(\binom{k}{2} = \frac{k(k-1)}{2}\) です。
\[
E[X] = \binom{k}{2} \times \frac{1}{365} = \frac{k(k-1)}{2 \times 365} = \frac{k(k-1)}{730}
\] この期待値 \(E[X]\) が1以上になる \(k\) を求めてみましょう。
\[
\frac{k(k-1)}{730} \ge 1
\] \[
k(k-1) \ge 730
\] \(k^2 \approx 730\) とすると \(k \approx \sqrt{730} \approx 27.01\)。したがって、\(k=28\) のときにこの不等式を満たします。
28人いれば、誕生日が一致するペア数の期待値は1以上になります。

この結果(期待値が1以上となるのが28人)は、確率が50%を超える23人という結果とは異なります。しかし、どちらの解析も、誕生日が一致する現象が、人数 \(n\) に対して \(\Theta(\sqrt{n})\) のオーダーで起こりうることを示しています(365日の場合は \(\sqrt{365} \approx 19.1\))。期待値が1以上というのは「平均して1つ以上のペアが一致する」という意味であり、確率が0.5を超えるというのは「少なくとも1つのペアが一致する可能性が半分以上」という意味です。期待値が1に近いとき、確率も0.5に近い値になる傾向がありますが、これらは異なる指標です。

 

ボールとビン / クーポンコレクター問題 (Balls and Bins / Coupon Collector's Problem)

問題

\(n\) 個のボールを、\(b\)個のビン(番号 1 から \(b\)) にランダムかつ独立に投げ入れます。各ボールが任意のビンに入る確率は等しく \(1/b\) です。

全てのビンに少なくとも1個のボールが入るまで、何個のボールを投げなければならないか(投げ入れ回数 \(n\) の期待値)を求めなさい。

 

この問題は、スーパーのキャンペーンで \(b\)種類のシールを集めようとしている人が、ランダムにシールがもらえるお菓子を何個買えば全ての種類のシールが集まるか、という状況に似ています。このため、「クーポンコレクター問題」とも呼ばれます。

この問題の期待値を計算するために、プロセスを段階に分け、各段階での投げ入れ回数の期待値を求め、それらを合計するというアプローチをとります。これは指示確率変数を使うほどではありませんが、期待値の線形性を効果的に使う例です。

証明

プロセスを以下の \(b\) 個の段階に分けます。

  • 第1段階: 0個のビンにボールが入っている状態から、1個目のビンにボールが入るまでの投げ入れ。
  • 第2段階: 1個のビンにボールが入っている状態から、2個目のビンにボールが入るまでの投げ入れ。
  • 第 \(i\) 段階:\(i-1\) 個の異なるビンにボールが入っている状態から、\(i\) 個目の異なるビンにボールが入るまでの投げ入れ。
  • 第 \(b\) 段階:\(b-1\) 個の異なるビンにボールが入っている状態から、\(b\) 個目の(最後の)ビンにボールが入るまでの投げ入れ。

第 i 段階が始まる時点では、既に \(i-1\) 個のビンにボールが入っています。まだボールが入っていないビンは \(b - (i-1) = b - i + 1\) 個あります。第 i段階での各投げ入れで、ボールがまだ空であるビンのいずれかに入る確率は、\(\frac{\text{空のビンの数}}{\text{全ビンの数}} = \frac{b - i + 1}{b}\) です。これを「成功」の確率と見なせます。

第 i 段階で必要な投げ入れ回数を確率変数 \(n_i\) とします。これは、成功確率 \(p_i = (b - i + 1)/b\) の**幾何分布**に従います。幾何分布の期待値(初めて成功するまでの試行回数の期待値)は \(1/p\) です。
したがって、第 i 段階に必要な投げ入れ回数の期待値は、
\[
E[n_i] = \frac{1}{p_i} = \frac{1}{(b - i + 1)/b} = \frac{b}{b - i + 1}
\] 全てのビンにボールが入る(すなわち、全 b 段階が終了する)までに必要な投げ入れ回数 n の総数は、各段階の投げ入れ回数 \(n_i\) の合計です。
\[
n = \sum_{i=1}^b n_i
\] 求めたいのはこの合計回数の期待値 \(E[n]\) です。期待値の線形性により、
\[
E[n] = E\left[\sum_{i=1}^b n_i\right] = \sum_{i=1}^b E[n_i] \] 各 \(E[n_i]\) を代入して、
\[
E[n] = \sum_{i=1}^b \frac{b}{b - i + 1}
\] ここで、和の添え字を \(j = b - i + 1\) と置き換えます。
i = 1 のとき \(j = b\)、 i = b のとき \(j = 1\) となります。
\[
E[n] = \sum_{j=1}^b \frac{b}{j} = b \sum_{j=1}^b \frac{1}{j} = b H_b
\] ここで \(H_b = \sum_{j=1}^b \frac{1}{j}\) は調和級数です。前回の証明で見たように、調和級数は自然対数と関係があり、\(H_b = \ln b + \gamma + O(1/b)\) です(\(\gamma\) はオイラー・マスケローニ定数)。\(O(1)\) という精度で書けば \(H_b = \ln b + O(1)\) です (テキストの式 A.9)。
したがって、全てのビンにボールが入るまでに必要な投げ入れ回数の期待値は、
$$
E[n] = b (\ln b + O(1))
$$
つまり、ビンの数 b が大きい場合、全てのビンにボールを入れるには、平均して約 \(b \ln b\) 回の投げ入れが必要になります。これは b に対して線形より少し大きいオーダーです。例えば、100種類のクーポンを全て集めるには、平均して約 \(100 \times \ln(100) \approx 100 \times 4.6 = 460\) 個のお菓子を買う必要があると期待されます。

 

 ストリーク (Streaks)

問題

公正なコインを \(n\) 回投げます。

期待される最長の連続した「表」(または「裏」)のストリークの長さはどれくらいでしょうか?

\(n\) 回のコイン投げの列 \((R_1, R_2, \ldots, R_n)\) を考えます。ここで \(R_i\) は \(i\) 回目の投げの結果(表または裏)です。最長のストリークの長さとは、列の中に同じ結果が連続して現れる最も長い部分列の長さです。例えば、「表表裏表表表裏」という投げ入れ列では、最長の表のストリークの長さは3です。

この問題の解析は少し複雑ですが、期待される最長ストリークの長さが、投げ入れ回数 \(n\) の対数 \(\lg n\) (2を底とする対数)のオーダーになることが示されます。すなわち、\(\Theta(\lg n)\) です。

この結果を示すために、期待される最長ストリーク長の**上限**と**下限**をそれぞれ評価します。

証明

上限の評価

長さ \(k\) の連続した表のストリークが、投げ入れ列のどこかに現れる確率を評価することで、最長ストリークの長さを上から抑えることができます。
長さ \(k\) の表のストリークは、位置 1 から始まるか、位置 2 から始まるか、...、位置 \(n-k+1\) から始まる可能性があります。
位置 \(i\) から始まる長さ \(k\) の表のストリークとは、投げ入れ \(R_i, R_{i+1}, \ldots, R_{i+k-1}\) が全て表である事象です。投げ入れは独立しており、各投げ入れが表になる確率は \(1/2\) なので、この事象が起こる確率は \((1/2)^k = 1/2^k\) です。
これを \(Pr\{A_{i,k}\}\) とします。

投げ入れ列の中に、少なくとも1つ長さ \(k\) の表のストリークが現れる事象は、これらの \(A_{i,k}\) という事象のいずれかが起こる事象 \(\cup_{i=1}^{n-k+1} A_{i,k}\) です。この確率を評価するために、ブールの不等式を使います (\(Pr\{\cup_j B_j\} \le \sum_j Pr\{B_j\}\))。
\[
Pr\{\text{長さ } k \text{ のストリークがどこかに現れる}\} = Pr\left\{\cup_{i=1}^{n-k+1} A_{i,k}\right\} \le \sum_{i=1}^{n-k+1} Pr\{A_{i,k}\}
\] \[
\le \sum_{i=1}^{n-k+1} \frac{1}{2^k} = \frac{n-k+1}{2^k} \le \frac{n}{2^k}
\] ここで、\(k\) を \(c \lg n\) (c は正の定数)と置いてみましょう。
\[
\frac{n}{2^{c \lg n}} = \frac{n}{2^{\lg (n^c)}} = \frac{n}{n^c} = \frac{1}{n^{c-1}}
\] もし \(c > 1\) であれば、この確率は \(n\) が大きくなるにつれて非常に小さくなります (\(1/n^{c-1} \to 0\))。
例えば、\(k = 2 \lg n\) とすると、長さ \(2 \lg n\) 以上のストリークが現れる確率は \(n/2^{2 \lg n} = n/n^2 = 1/n\) 以下になります。これは、\(n\) が大きい場合、長さが \(2 \lg n\) を超えるストリークが現れる可能性は低いことを示しています。

期待される最長ストリークの長さ \(L\) は、その定義から \(E[L] = \sum_{j=0}^n j \cdot Pr\{L=j\}\) と書けます。ここで \(L=j\) は最長ストリークの長さがちょうど \(j\) である事象です。
長さ \(k\) 以上のストリークが現れる確率 \(Pr\{L \ge k\}\) は、ブールの不等式から \(Pr\{L \ge k\} \le n/2^k\) です。
期待値 \(E[L]\) を以下の2つの部分に分けて評価します。
\(E[L] = \sum_{j=0}^{k-1} j \cdot Pr\{L=j\} + \sum_{j=k}^n j \cdot Pr\{L=j\}\)
ここで、\(k\) として例えば \(2 \lg n\) を選びます。
\[
E[L] \le \sum_{j=0}^{2\lg n - 1} (2\lg n - 1) \cdot Pr\{L=j\} + \sum_{j=2\lg n}^n n \cdot Pr\{L=j\}
\] \[
\le (2\lg n) \sum_{j=0}^{2\lg n - 1} Pr\{L=j\} + n \sum_{j=2\lg n}^n Pr\{L=j\}
\] \(\sum_{j=0}^{2\lg n - 1} Pr\{L=j\} \le \sum_{j=0}^n Pr\{L=j\} = 1\) です。
\(\sum_{j=2\lg n}^n Pr\{L=j\} = Pr\{L \ge 2\lg n\}\) です。ブールの不等式より \(Pr\{L \ge 2\lg n\} \le n/2^{2\lg n} = 1/n\) です。
したがって、
\[
E[L] \le (2\lg n) \times 1 + n \times \frac{1}{n} = 2\lg n + 1
\] これは、期待される最長ストリーク長が \(O(\lg n)\) であることを示しています。

下限の評価

次に、期待される最長ストリークの長さが \(\Omega(\lg n)\) であることを示します。これは、長さが \(\lg n\) のオーダーであるストリークが、高い確率で現れることを示せば十分です。

\(n\) 回の投げ入れを、それぞれ長さ \(s\) の連続する部分に分けます。約 \(n/s\) 個のグループができます。\(s\) の値として、例えば \(s = \lfloor (\lg n) / 2 \rfloor\) を選びます。
特定のグループ(長さ \(s\))が全て表になる確率は \(1/2^s = 1/2^{\lfloor (\lg n)/2 \rfloor}\) です。
\[
\frac{1}{2^{\lfloor (\lg n)/2 \rfloor}} \ge \frac{1}{2^{(\lg n)/2}} = \frac{1}{\sqrt{n}}
\] したがって、特定のグループが全て表にならない確率は \(1 - 1/2^s \le 1 - 1/\sqrt{n}\) です。

約 \(n/s\) 個のグループは、ほぼ独立したコイン投げから形成されます。これらのグループの**全て**が全て表にならない確率は、それぞれのグループが全て表にならない確率を掛け合わせたものとして近似できます。
この確率は \((1 - 1/2^s)^{\approx n/s}\) です。不等式 \((1-x)^m \le e^{-mx}\) を用いると、
\[
\left(1 - \frac{1}{2^s}\right)^{n/s} \le e^{-(n/s)/2^s} = e^{-n/(s 2^s)}
\] \(s = \lfloor (\lg n)/2 \rfloor\) なので、\(2^s \approx \sqrt{n}\) です。\(s \approx (\lg n)/2\) です。
指数部分は \( -n / (s 2^s) \approx -n / ((\lg n)/2 \cdot \sqrt{n}) = -2\sqrt{n} / \lg n \) です。
この指数は \(n\) が大きくなるにつれて負の無限大に発散するので、確率は 0 に収束します。
実際、テキストでは \(e^{-(2n/\lg n - 1)/\sqrt{n}} = O(e^{-\ln n}) = O(1/n)\) であることが示されています 。
つまり、全てのグループが全て表にならない確率は非常に小さい (\(O(1/n)\)) です。

これは逆に、**少なくとも1つのグループが全て表になる確率が非常に高い** (\(1 - O(1/n)\)) ことを意味します。もし少なくとも1つのグループが全て表になれば、その長さ \(s = \lfloor (\lg n)/2 \rfloor\) のストリークが必ず存在することになります。
したがって、\(Pr\{L \ge s\} \ge 1 - O(1/n)\) です 。

期待値 \(E[L]\) を再び評価します。
\[
E[L] = \sum_{j=0}^{s-1} j \cdot Pr\{L=j\} + \sum_{j=s}^n j \cdot Pr\{L=j\}
\] ここで \(s = \lfloor (\lg n)/2 \rfloor\) です。
\[
E[L] \ge \sum_{j=s}^n j \cdot Pr\{L=j\} \ge \sum_{j=s}^n s \cdot Pr\{L=j\} = s \sum_{j=s}^n Pr\{L=j\} = s \cdot Pr\{L \ge s\}
\] \[
\ge \lfloor (\lg n)/2 \rfloor \times (1 - O(1/n))
\] \(n \to \infty\) のとき、\(\lfloor (\lg n)/2 \rfloor\) は \(\Omega(\lg n)\) で増加し、\((1 - O(1/n))\) は1に近づきます。
したがって、\(E[L] = \Omega(\lg n)\) であることが示されました。

期待される最長ストリーク長が \(O(\lg n)\) かつ \(\Omega(\lg n)\) であることから、**\(\Theta(\lg n)\)** であることが結論付けられます。

 

オンライン採用問題 (Online Hiring Problem)

問題

\(n\) 人の候補者が順番に面接に来ます。あなたは各候補者と面接した後、直ちにその場で採用するか、拒否するかを決めなければなりません。一度拒否した候補者を後で採用することはできません。目標は、最も優秀な候補者(全体の最高ランクの候補者)を一人だけ採用することです。候補者はランダムな順序で現れると仮定します。

どのような戦略をとれば、最も優秀な候補者を採用できる確率を最大化できるでしょうか? そしてその最大確率は?

 

この問題は、これまでの採用問題の変種です。全ての候補者と面接する前に決定を下す必要がある「オンライン」な問題です。

採用戦略として、以下のシンプルな方法を考えます。
まず、最初の \(k\) 人の候補者と面接しますが、彼らを絶対に採用しません。彼らの面接を通して、これまでの最高ランク(最高のスキルを持つ候補者)が誰かを記録しておきます。
次に、\(k+1\) 番目以降の候補者と面接します。このとき、もし面接した候補者が、最初の \(k\) 人の中で最も優秀だった候補者よりも優秀であれば、その候補者を直ちに採用し、プロセスを終了します。
もし、\(n\) 番目の候補者まで誰も採用しなかった場合、最後の \(n\) 番目の候補者を(たとえ最初の \(k\) 人より優秀でなくても)採用します。

この戦略において、最も優秀な候補者を採用できる確率は、最初の \(k\) 人を何人「見送るか」という \(k\) の値に依存します。\(k\) が小さすぎると、すぐに誰かを採用してしまい、後に来るかもしれないもっと優秀な候補者を逃す可能性があります。\(k\) が大きすぎると、最も優秀な候補者自身が最初の \(k\) 人の中に入ってしまい、採用する機会を逃してしまいます。最適な \(k\) が存在しそうです。

候補者はランダムな順序で現れると仮定します。最も優秀な候補者を採用できる確率 \(Pr\{S\}\) を計算します。
最も優秀な候補者が \(i\)番目に現れた場合に、この戦略が成功する事象を \(S_i\) とします。これらの事象 \(S_i\) は、互いに排反(同時に起こらない)です。全体の成功確率は、それぞれの事象が起こる確率の合計です。
\[
Pr\{S\} = \sum_{i=1}^n Pr\{S_i\}
\] 戦略上、最初の \(k\) 人は採用しません。したがって、もし最も優秀な候補者が最初の \(k\) 人の中にいた場合(つまり \(i \le k\) の場合)、戦略は成功しません (\(Pr\{S_i\} = 0\) for \(i \le k\))。
成功する可能性があるのは、最も優秀な候補者が \(k+1\) 番目以降に現れた場合のみです (\(i > k\))。
\[
Pr\{S\} = \sum_{i=k+1}^n Pr\{S_i\}
\] では、\(i > k\) の場合の \(Pr\{S_i\}\) はいくつでしょうか? 最も優秀な候補者が \(i\) 番目に現れたときに戦略が成功するためには、以下の2つのことが同時に起こる必要があります。
1. 全体の最も優秀な候補者が、ちょうど \(i\) 番目の位置にいる。この事象を \(B_i\) とします。候補者はランダムな順序で現れるので、最も優秀な候補者がどの位置に現れる可能性も等しいです。したがって、\(Pr\{B_i\} = 1/n\) です。
2. \(k+1\)番目から \(i-1\) 番目までの候補者の誰も採用されなかった。この事象を \(O_i\) とします。戦略によると、これは、これらの候補者たちが、最初の \(k\) 人の中で最も優秀だった候補者よりも優秀でなかった場合に起こります。

事象 \(B_i\) と \(O_i\) は独立です。なぜなら、\(B_i\) は \(i\) 番目の候補者の絶対的なランク(全体の中で一番)に関することであり、\(O_i\) は \(k+1\) 番目から \(i-1\) 番目までの候補者の、最初の \(k\) 人の中での最高ランクに対する相対的なランクに関することだからです。これらは互いに影響しません。
したがって、\(Pr\{S_i\} = Pr\{B_i \cap O_i\} = Pr\{B_i\} \times Pr\{O_i\}\) です。

\(Pr\{O_i\}\) はいくつでしょうか? 事象 \(O_i\) は、「候補者 \(k+1\) から \(i-1\) の中に、最初の \(k\) 人の誰よりも優秀な候補者はいなかった」という事象です。これは言い換えれば、「最初の \(i-1\) 人の候補者の中で最も優秀だった候補者が、最初の \(k\) 人の中にいた」という事象と同じです。
最初の \(i-1\) 人の候補者はランダムな順序で現れています。この \(i-1\) 人の中で最も優秀な候補者が誰である可能性も等しく高いです。その中で、最も優秀な候補者が最初の \(k\) 人の中にいる確率は、\(\frac{\text{最初の } k \text{ 人}}{\text{最初の } i-1 \text{ 人}} = \frac{k}{i-1}\) です。したがって、\(Pr\{O_i\} = k/(i-1)\) です(\(i-1 \ge k\) と仮定。もし \(i-1 < k\) なら \(O_i\) は常に真で確率は1ですが、ここでは \(i > k\) の場合を考えているので \(i-1 \ge k\) です)。

\(i > k\) の場合の \(Pr\{S_i\}\) は、
\[
Pr\{S_i\} = Pr\{B_i\} \times Pr\{O_i\} = \frac{1}{n} \times \frac{k}{i-1} = \frac{k}{n(i-1)}
\] 全体の成功確率 \(Pr\{S\}\) は、
\[
Pr\{S\} = \sum_{i=k+1}^n Pr\{S_i\} = \sum_{i=k+1}^n \frac{k}{n(i-1)}
\] 和の添え字を \(j = i-1\) と置き換えると、\(i=k+1\) のとき \(j=k\)、\(i=n\) のとき \(j=n-1\) となります。
\[
Pr\{S\} = \frac{k}{n} \sum_{j=k}^{n-1} \frac{1}{j}
\] この和は、調和級数 \(H_{n-1} - H_{k-1}\) です。大きな \(n\) に対して、この和は積分を用いて近似できます。
\[
\sum_{j=k}^{n-1} \frac{1}{j} \approx \int_k^n \frac{1}{x} dx = [\ln x]_k^n = \ln n - \ln k = \ln\left(\frac{n}{k}\right)
\] したがって、成功確率はおよそ
\[
Pr\{S\} \approx \frac{k}{n} \ln\left(\frac{n}{k}\right)
\] この近似式を最大にする \(k\) を求めます。関数 \(f(k) = \frac{k}{n} \ln\left(\frac{n}{k}\right)\) を \(k\) について微分し、0と置きます。
\(f(k) = \frac{1}{n} (k \ln n - k \ln k)\)
\(f'(k) = \frac{1}{n} (\ln n - (1 \cdot \ln k + k \cdot \frac{1}{k})) = \frac{1}{n} (\ln n - \ln k - 1)\)
\(f'(k) = 0\) となるのは、\(\ln n - \ln k - 1 = 0\) 、すなわち \(\ln n - 1 = \ln k\) 、\(\ln(n/e) = \ln k\) のときです。
したがって、最適な \(k\) は、
\[
k = \frac{n}{e}
\] ここで \(e\) は自然対数の底(約2.718)です。
最適な戦略は、**最初の約 \(n/e\) 人を見送り、それ以降で最初の \(n/e\) 人の誰よりも優秀な候補者が現れたら採用する**ことです。

この最適な \(k = n/e\) を成功確率の近似式に代入すると、最大の成功確率が得られます。
\[
Pr\{S\} \approx \frac{n/e}{n} \ln\left(\frac{n}{n/e}\right) = \frac{1}{e} \ln(e) = \frac{1}{e}
\] したがって、最適な戦略をとった場合、最も優秀な候補者を採用できる確率は、候補者の数 \(n\) にかかわらず、およそ \(1/e \approx 0.368\) となります。これは、約36.8%の確率で全体の最も優秀な候補者を雇えることを意味します。たとえ全体のリストを全て見られなくても、ランダムな順序という性質を利用することで、意外と高い確率で最高の候補者を見つけられるのです。

まとめ

本記事は、コンピューター科学における「ランダム性」が、アルゴリズムの性能を向上させる強力なツールであることを解説しています。通常、アルゴリズムは予測可能な決まった手順で動作しますが、「意地悪な入力」によって効率が著しく低下することがあります。ランダム性を利用することで、この問題を回避し、効率的で安定した性能を実現できます。

 

 

 

 

-アルゴリズム