在我了解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))
有人可以解释第一种算法是不正确的吗?(即不会产生随机洗牌)。
从维基百科:
同样,每次迭代时始终从有效数组索引的整个范围中选择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个中洗牌。
本质上,您在混洗中引入了细微的偏差,这将导致某些排列出现的频率比其他排列高。它通常不是很引人注目,但是它可能会使某些敏感的应用程序(例如排列的蒙特卡洛模拟)无法产生准确的答案。