Knuth Shuffle
问题描述
Knuth Shuffle,也称作Fisher-Yates Shuffle,是一种对一个有限序列生成随机排列的算法。
算法描述
假设原数组为 a [ ] a[] a[],长度为 n n n,从最后一个元素开始,产生一个 0 0 0到 n − 1 n-1 n−1的随机整数 j j j,并将交换 a [ j ] a[j] a[j]与 a [ n − 1 ] a[n-1] a[n−1]的值;这样便确定了最后结果中 a [ n − 1 ] a[n-1] a[n−1]的值;之后,产生下一个 0 0 0到 n − 2 n-2 n−2的随机整数 j j j,交换 a [ j ] a[j] a[j]与 a [ n − 2 ] a[n-2] a[n−2]的值,这样便确定了最后结果中 a [ n − 2 ] a[n-2] a[n−2]的值;重复这个步骤直到确定 a [ 1 ] a[1] a[1]。
算法实现
public void knuthShuffle(int[] a) {
for (int i = a.length - 1; i > 0; i -= 1) {
int j = StdRandom.Uniform(i + 1);
//Swap(a[j], a[i])
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
算法证明
从第一次循环可以看出,任何一个元素出现在 a [ n − 1 ] a[n-1] a[n−1]的概率是均等的,都是 1 n \frac{1}{n} n1。在第二次循环中,任何一个元素出现在 a [ n − 2 ] a[n-2] a[n−2]的概率为 ( 1 − 1 n ) × 1 n − 1 = 1 n (1-\frac{1}{n})\times\frac{1}{n-1}=\frac{1}{n} (1−n