145人阅读 评论(0)

# Random Shuffle

Goal. Rearrange array so that result is a uniformly random permutation.
（洗牌算法）

## Shuffle Sort

• Generate a random real number for each array entry.
• Sort the array. (以随机数为key来排序，每个item和对应的随机数一起exchange)

## Linear Shuffle

### Algorithm

O(n)$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]

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);
}
}

### 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]$S[1], S[2], \dots, S[n]$来表示array中的n个元素，为证明该命题，只需证明如下引理

Lemme. The list of elements (S[1],,S[n])$(S[1], \dots, S[n])$ at the end of the algorithm can be any of the n!$n!$
permutations with the same probability.

• i=1$i=1$时，只有S[1]$S[1]$一个元素，只有一种排列，显然成立；
• 假设i=k$i=k$时，命题成立；
• i=k+1$i=k+1$时，令x$x$为第k+1$k+1$次循环中生成的随机数，P$P$k+1$k+1$次循环之前数组(S[1],,S[k])$(S[1], \dots, S[k])$的排列，P$P'$表示第k+1$k+1$次循环之后数组的排列，则P$P'$(P,x)$(P, x)$的函数。则根据命题，P$P$k!$k!$种可能，而1xk+1$1 \le x \le k+1$，因此pair (P,x)$(P, x)$共有(i+1)!$(i+1)!$中可能。
• 下面证明：

• Fact 1: each pair of (P,x)$(P,x)$ happens with the same probability in the algorithm.
(P,x)$(P,x)$的每种情况等概率）
• Fact 2: each pair of (P,x)$(P,x)$ produces a distinct P$P'$.
(P,x)$(P,x)$的每种情况结果各不相同）

• Proof of Fact 1. 根据归纳假设，P$P$可能的k!$k!$种情况等概率，而x$x$也是等概率生成的，即x$x$[1,,k+1]$[1, \dots, k+1]$中的任何一个数的概率都是1/(k+1)$1/(k+1)$，因此每种(P,x)$(P,x)$ pair 出现的概率都为1/(k+1)!$1/(k+1)!$

• Proof of Fact 2.(P1,x1),(P2,x2)$(P_1, x_1), (P_2, x_2)$为两个不同的pair，则至少满足如下两个不等式中的一个P1P2,x1x2$P_1 \ne P_2, x_1 \ne x_2$。令P1,P2$P'_1, P'_2$为上述两个pair分别所生成的，

• Case 1: P1=P2$P_1 = P_2$. 则x1x2$x_1 \ne x_2$，因此P1,P2$P'_1, P'_2$在第k+1$k+1$个位置拥有不同的元素（分别为S[x1],S[x2]$S[x_1], S[x_2]$）；

• Case 2：P1P2$P_1 \ne P_2$. 设P1$P_1$P2$P_2$在位置j$j$上有不同的元素。若x1x2$x_1 \ne x_2$x1=x2j$x_1 = x_2 \ne j$，那么P1,P2$P'_1, P'_2$仍然在位置j$j$拥有不同的元素； 否则（x1=x2=j$x_1 = x_2 = j$），P1,P2$P'_1, P'_2$在位置k+1$k+1$有不同的元素。

$\square$

## A Common Mistake

The naïve algorithm.

for i=0 to n-1
swap(A[i], A[random(n)])

1. Shuffling
2. The Danger of Naïveté

# Python - random.shuffle

Python random module中shuffle的源码，使用Knuth-Durstenfeld Shuffle算法。

def shuffle(self, x, random=None, int=int):
"""x, random=random.random -> shuffle list x in place; return None.

Optional arg random is a 0-argument function returning a random
float in [0.0, 1.0); by default, the standard random.random.
"""

randbelow = self._randbelow
for i in reversed(range(1, len(x))):
# pick an element in x[:i+1] with which to exchange x[i]
j = randbelow(i+1) if random is None else int(random() * (i+1))
x[i], x[j] = x[j], x[i]
0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：1756次
• 积分：95
• 等级：
• 排名：千里之外
• 原创：7篇
• 转载：1篇
• 译文：0篇
• 评论：0条
文章分类
文章存档
阅读排行