你会说现代版本的渔民是最无偏见的改组算法吗? 您如何解释数组中的每个元素都有1 / n的概率在其原始位置?
答案 0 :(得分:7)
给定一个完美的伪随机数生成器(Mersenne Twister非常接近),Fisher-Yates算法是完全无偏的,因为每个排列具有相同的发生概率。这很容易用感应证明。 Fisher-Yates算法可以如下递归写入(在Python语法伪代码中):
def fisherYatesShuffle(array):
if len(array) < 2:
return
firstElementIndex = uniform(0, len(array))
swap(array[0], array[firstElementIndex])
fisherYatesShuffle(array[1:])
每个索引被选为firstElementIndex
的概率相等。当你递归时,你现在有相同的概率选择任何仍然留下的元素。
编辑:算法已在数学上证明是无偏见的。由于该算法是非确定性的,因此在统计上测试实现是否正常工作的最佳方法。我会采用一些任意但小的大小的数组,将其多次洗牌(从每次输入的相同排列开始)并计算每个输出排列发生的次数。然后,我会使用Pearson's Chi-square Test测试此分布的均匀性。
答案 1 :(得分:3)
(现代,又称“Knuth”)Fisher–Yates洗牌是
我们还能从算法中得到什么呢?嗯,是的,当排列数量变大时,人们可能会尝试别的东西,但大多数情况下并没有涉及如此巨大的数量?)
修改强>:
'只是注意到这个答案回应了问题的标题,而不是内容。 (这就是为什么让问题的这两部分更好地匹配是好的...)
简而言之,shuffle 与用于实现算法的特定RNG 一样随机。
一个直观的解释是,对于具有m个元素的数组,即使作为n,循环的减小控制变量向下变为1,位置n处的单元格可能被交换的可能单元减少,这个单元格的概率减小很容易被移动增加的比例完全相同。换句话说,数组的最后一个元素可以在数组中的任何位置结束,但它只有一次机会被移动(在第一次迭代时)。要移动的倒数第二个元素的位置要少一个,但是在第一次迭代期间可能很容易移动的概率为1 / m。等