とある偽シャッフルアルゴリズムとその分布
次のようなシャッフルアルゴリズムを考える(簡単のためrand()%N
と表記したが、この部分で0以上N-1未満の一様な整数乱数が生成されると仮定して議論する)。出力されるものは 0, ..., 255 を並び換えたもの(置換)である。
std::vector<int> a(N); for(int i = 0; i < N; ++i) { a[i] = i; } for(int i = 0; i < N; ++i) { std::swap(a[i], a[rand()%N]); }
このアルゴリズムは均一ではない。a[i]==j
となる確率は、 i < j
のときに高くなり、j <= i
のときに低くなる。グラフにすると以下のようになる。
証明
2個目のループの本体が 回 実行された時点で a[i]==j
となる確率を とおく。プログラムをジッと睨むと、以下の式を得る:
さらに、不変条件 に注目すると、後者の式は
となる。このとき、以下が成り立つことを示す。 の場合が定理の主張に他ならない。
に関する帰納法で示す。まず、 が上記を満たすことはすぐにわかる。
各 について が上記を満たすと仮定する。このとき、各 について も上記を満たすことを示す。そのために以下のように場合分けをする。
- のとき。
- のとき。
- のとき。
- のとき。
- のとき。
- のとき。
- のとき。
- のとき。
- のとき。
- のとき。
各場合分けは簡単な式変形で示せる。