洗牌算法或者叫打乱数组顺序算法

for(int i = n - 1; i >= 0 ; i -- )
    swap(arr[i], arr[rand(0, i)]) // rand(0, i) 生成 [0, i] 之间的随机整数

从后往前交换是因为生成 [0, i] 范围的随机数比生成 [i, n) 范围的随机数简单,直接对 i+1 求余就好了。

n个数有n!种组合,这样交换可以实现产生的每个组合是等可能的。

再解释一下为什么这么做,这个思想就是 n * (n-1) * (n-2) * ....2 * 1,我们从倒数第一个位置开始,有n种选择(arr[0]......arr[n-1])倒数第二个有n-1中选择(arr数组里面除去放在倒数第一个的数,剩下n-1个),那么直到第一个,剩下一种选择。所有的就遍历完了。每种组合的可能性都是均等的。 这行代码主要的就是可能性均等。

有一个大小为100的数组,里面的元素是从 1 到 100 按顺序排列,怎样随机的从里面选择 50 个数?注意数字不能重复!

就可以先打乱在取其中50个。直接产生随机数作为下标是会重复的。

或者弄一个数组,把每一次随机的数都放到数组里,下一次随机就看这个数组里面有没有这数,有的话就继续随机,直到这个数组里面有 50 个数字就停止。这个可以,但是,越往后选择的数字跟前面已经挑选的数字重复的概率越高,这就会造成如果数组很大,选择的数字数目也很大的话,重复次数在量级上会很大。

posted on 2021-06-11 10:23  雾恋过往  阅读(110)  评论(0编辑  收藏  举报

Live2D