【数学】Knuth洗牌算法及其证明

假设有 n n n张牌,每个牌编号 1 ∼ n 1\sim n 1n,要求设计一个随机算法,返回 1 ∼ n 1\sim n 1n组成的序列,但排列顺序要求是完全随机的。完全随机的意思是,首先显然有 n ! n! n!个排列可能性,完全随机就是指,返回的序列出现的概率是 1 n ! \frac{1}{n!} n!1

我们直接给出算法的python代码:

import random

def shuffle(cards):
    for k in range(len(cards)):
        i = random.randint(k, len(cards) - 1)
        cards[i], cards[k] = cards[k], cards[i]

算法的大致意思是,先从第 1 ∼ n 1\sim n 1n里随机选一个位置的数,将其与第一个数交换;接着从第 2 ∼ n 2\sim n 2n里随机选一个位置的数,将其与第二个数交换;如此操作下去,得到的序列就是完全随机排列的。该算法时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1),是非常优秀的算法了。

我们说明一下这个算法的性质。
首先,每个数出现在第 1 1 1位的概率显然是 1 n \frac{1}{n} n1。接着考虑每个数出现在第 2 2 2位的概率,根据条件概率公式,其概率为 1 n 0 + n − 1 n 1 n − 1 = 1 n \frac{1}{n}0+\frac{n-1}{n}\frac{1}{n-1}=\frac{1}{n} n10+nn1n11=n1。以此类推可知,每个数出现在第 k k k位的概率都等于 1 n \frac{1}{n} n1

其次,每个排列取到的概率都是 1 n ! \frac{1}{n!} n!1。给定一个排列 ( a 1 , a 2 , . . . , a n ) (a_1,a_2,...,a_n) (a1,a2,...,an),第一遍循环中 a 1 a_1 a1恰好换到第 1 1 1位的概率是 1 n \frac{1}{n} n1,第二遍循环中 a 2 a_2 a2恰好换到第 2 2 2位的概率是 1 n − 1 \frac{1}{n-1} n11,以此类推。根据乘法原理,排列 ( a 1 , a 2 , . . . , a n ) (a_1,a_2,...,a_n) (a1,a2,...,an)出现的概率是 1 n 1 n − 1 1 n − 2 . . . 1 1 = 1 n ! \frac{1}{n}\frac{1}{n-1}\frac{1}{n-2}...\frac{1}{1}=\frac{1}{n!} n1n11n21...11=n!1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值