Fisher-Yates shuffle提供了一个很好的算法,可以在一次传递中对长度为A
的数组n
进行混洗:
For k = 1 to n
Pick a random integer j from k to n
Swap A[k] and A[j]
单次通过此算法后,A
的条目会随机均匀出现。
破坏此算法的常用方法是执行以下操作:
For k = 1 to n
Pick a random integer j from 1 to n
Swap A[k] and A[j]
通过此算法单次传递的结果分布不均匀随机,并且对此帖子的内容进行了很好的讨论:What distribution do you get from this broken random shuffle?
我最近阅读了Diaconis,Fulman和Holmes题为Analysis of Casino Shelf Shuffling Machines的一篇令人愉快的文章,其中作者描述了一个物理机器进行以下批量洗牌:
For k = 1 to n
Pick a random integer j from 1 to 10
Randomly choose to place card k on the top or bottom of stack j
作者提出的问题是,在一次通过后,这是否给出了合理的随机排序。答案肯定不是。在这次洗牌中看到缺陷的一种方法是从一副卡片开始,这些卡片在n/2
黑卡顶上有n/2
张红牌。一次通过后产生的牌组最多会有10块红牌!对于n = 52*6
,这不是非常随意的。作者还表明,一次洗牌的最佳“猜测下一张牌”策略平均可以正确猜测9.5张牌,而随机牌组的最佳策略平均只能正确猜测4.5张牌。
是否有任何其他有趣的单通道随机播放实现近乎随机性和/或有趣的分布?我特别感兴趣的是与后者相似的shuffle,这些shuffle适用于批量条目。
答案 0 :(得分:1)
如果你有一个洗牌桌,你希望将一批新牌洗牌(你知道没有一张牌是重复的),那么我认为以下内容是有效的。
ForEach card in batch:
gap = random(deck.size() + 1) # choose a gap between cards, before first, or after last.
deck.insertAt(gap,card)
分发
随机的分布是均匀的,并且甲板的顺序不变,所以仍然是均匀的。 我认为结果应该是统一的。 (我的统计数据太生锈了,无法确定)。
时间
假设insertAt是O(1)而不是O(N) - 这取决于套牌的实现 - 整个例程是O(批量大小) - 这是你希望最好的,因为你必须处理每张卡