Random Shuffle
Goal. Rearrange array so that result is a uniformly random permutation.
(洗牌算法)
Shuffle Sort
使用排序算法来shuffle:
- Generate a random real number for each array entry.
- Sort the array. (以随机数为key来排序,每个item和对应的随机数一起exchange)
分析: 复杂度为 O(nlogn) 。
Linear Shuffle
Algorithm
O(n) 复杂度的shuffle算法——Fisher–Yates shuffle (Knuthe shuffle)。
- In iteration i , pick integer r between 0 and i uniformly at random.
- Swap a[i] and a[r].
Pseudo-code:
/*
Input: an array a of length n.
Output: an shuffled array a.
*/
For i = 0 to n-1
r = random number that in [0,i]
swap a[i] and a[r]
或者从后往前循环(Knuth-Durstenfeld Shuffle)
To shuffle an array a of n elements (indices 0..n-1):
for i from n − 1 downto 1 do
j ← random integer such that 0 ≤ j ≤ i
exchange a[j] and a[i]
Java code. ( From Algorithm 4th.)
public static void shuffle(Object[] a)
{
int N = a.length;
for (int i = 0; i < N; i++)
{
// generate random number between 0 and i
int r = StdRandom.uniform(i + 1);
exch(a, i, r);
}
}
注意: 产生随机数的范围为 [0,i] ,而不是 [0,n−1] 。
Proof
Proposition. [Fisher-Yates 1938] Fisher-Yates shuffling algorithm produces a
uniformly random permutation of the input array in linear time.
Proof.1
用 S[1],S[2],…,S[n] 来表示array中的n个元素,为证明该命题,只需证明如下引理
Lemme. The list of elements (S[1],…,S[n]) at the end of the algorithm can be any of the n!
permutations with the same probability.
即, (S[1],…,S[n]) 在算法结束时,可以等概率地生成所有 n! 排列中的任何一个。
使用归纳法来证明:
当算法完成 i=k(1≤k≤n) 次循环后,数组 (S[1],…,S[k]) 可以等概率地生成所有 k! 排列中的任何一个。
- 当 i=1 时,只有