小编典典

为什么这种混洗算法是错误的?

algorithm

在我了解Fisher-Yates之前,这是我想出的算法:

def sort(arr):
    for i in range(len(arr)):
        swap(arr, i, rand.randint(0, len(arr) - 1))

根据我的理解,这与Fisher-Yates之间的唯一区别是:

swap(arr, i, rand.randint(0, len(arr) - 1))

我应该写:

swap(arr, i, rand.randint(i, len(arr) - 1))

有人可以解释第一种算法是不正确的吗?(即不会产生随机洗牌)。


阅读 215

收藏
2020-07-28

共1个答案

小编典典

从维基百科:

同样,每次迭代时始终从有效数组索引的整个范围中选择j也会产生有偏差的结果,尽管这种情况不太明显。从这一事实可以看出,这样做会产生n
n个不同的可能交换序列,而只有n!n元素数组的可能排列。由于n ñ永远不能被n整除!当n>
2(因为后者是通过n-1个,这股无素因子具有n整除),一些置换必须由多个n个产生Ñ交换顺序比其他顺序。作为这种偏差的具体示例,请观察对三元素数组进行改组的可能结果的分布[1、2、3]。该数组有6个可能的排列(3!=
6),但是该算法会产生27种可能的混洗(3 3 =
27)。在这种情况下,[1、2、3],[3、1、2]和[3、2、1]分别来自27个混洗中的4个,而其余3个排列中的每个均发生在27个混洗中的5个中洗牌。

本质上,您在混洗中引入了细微的偏差,这将导致某些排列出现的频率比其他排列高。它通常不是很引人注目,但是它可能会使某些敏感的应用程序(例如排列的蒙特卡洛模拟)无法产生准确的答案。

2020-07-28