随机洗牌算法Knuth Shuffle和错排公式

Posted zefengyao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了随机洗牌算法Knuth Shuffle和错排公式相关的知识,希望对你有一定的参考价值。

Knuth随机洗牌算法:譬如现在有54张牌,如何洗牌才能保证随机性。可以这么考虑,从最末尾一张牌开始洗,对于每一张牌,编号在该牌前面的牌中任意一张选一张和当前牌进行交换,直至洗到第一张牌为止。参考代码如下:

void knuth() {
        for (int i = 54; i > 1; i--) {
            int id = rand() % (i - 1) + 1;
            swap(a[i], a[id]);
        }
    }

由上述方法可知,每一张牌经过洗牌之后一定不会出现在原来位置,那么一共会有多少情况呢,这其实就是错排的定义,n个数的错排数有如下递推公式:

f(n)=(n-1)(f(n-1)+f(n-2))

公式的推导:首先让我们假设已知n-1个数和n-2个数的错排数,这时又在原来基础上加了一个数字,那么如果这n个数要构成错排,新加入的数字一定不能出现在自己的位置上,所以它只能选择其余的n-1个位置,不妨设选择了第k个位置,那么原本在第k个位置上的数又会跑到哪里去呢,这里有两种情况,原本的第k个数跑到第n个数的位置上去了,这时这两个数只是相互交换了位置,其余的n-2个数怎么排列完全不受影响,故此时有f(n-2)种情况;再考虑原本第k个数不在第n个数的位置上,那么除去第n个数,其余的n-1个数任然构成错排,错排数为f(n-1)。至此就可得递推式f(n)=(n-1)(f(n-1)+f(n-2));

 

以上是关于随机洗牌算法Knuth Shuffle和错排公式的主要内容,如果未能解决你的问题,请参考以下文章

Shuffle an Array (水塘抽样)

数组洗牌算法-shuffle

PAT 线上测试赛 2020-05-01

PAT 线上测试赛真题(2020-05-01)

Python中的键控随机洗牌

Javascript 洗牌算法,打乱数组,随机获取元素