选择单个随机值组合的算法?

35 algorithm combinations

说我有y不同的值,我想x随机选择它们.这样做的有效算法是什么?我可以打电话给rand() x时间,但如果很大x,表现会很差y.

请注意,此处需要组合:每个值应具有相同的概率,但结果中的顺序并不重要.当然,任何生成算法都是合格的,但我想知道如果没有随机顺序要求,是否可以更有效地做到这一点.

如何有效地生成0和上限N之间的K个非重复整数的列表,涵盖了这种情况的排列.

Jer*_*fin 57

Robert Floyd为这种情况发明了一种采样算法.它通常优于洗牌然后抓取第一个x元素,因为它不需要O(y)存储.如最初编写的那样,它假定来自1..N的值,但是通过简单地将它产生的值作为下标处理为向量/数组/其他来生成0..N和/或使用非连续值是微不足道的.

在pseuocode中,算法就像这样运行(从Jon Bentley的Programming Pearls专栏"Brilliance的样本"中窃取).

initialize set S to empty
for J := N-M + 1 to N do
    T := RandInt(1, J)
    if T is not in S then
        insert T in S
    else
        insert J in S
Run Code Online (Sandbox Code Playgroud)

最后一点(如果T已经在S中则插入J)是棘手的部分.最重要的是,它确保插入J的正确数学概率,以便产生无偏的结果.

关于O(x)存储,它是O(x)1O(1).y

注意,根据问题中的标签,算法仅保证结果中出现的每个元素的概率相等,而不是它们在其中的相对顺序.


在最坏的情况下,所涉及的哈希映射可以忽略1 O(x 2),因为它是一个几乎不存在的病态情况,其中所有值都具有相同的哈希值

  • 我花了一些时间来证明练习的正确性.我发布了它http://math.stackexchange.com/questions/178690/whats-the-proof-of-correctness-for-robert-floyds-algorithm-for-selecting-a-sin (13认同)
  • @BrunoCosta:我想这取决于你对"作品"的意思.正如它为结果产生一个集合所暗示的那样,它更多地是关于*选择的*数字而不是订单.如果你问它从1到N的N个数字,它会这样做(但是,它们将按顺序生成).结果的顺序将取决于您使用的"Set"如何命令其内容. (3认同)
  • 发现它...... ACM的通讯,1987年9月,第30卷,第9期. (2认同)

Ste*_*sop 11

假设您希望订单也是随机的(或者不介意它是随机的),我只会使用截断的Fisher-Yates shuffle.启动随机播放算法,但是一旦选择了第一个x值就停止,而不是"随机选择"所有y这些值.

Fisher-Yates的工作原理如下:

  • 随机选择一个元素,并将其与数组末尾的元素交换.
  • 递归(或更可能迭代)数组的其余部分,不包括最后一个元素.

第一步之后的步骤不要修改数组的最后一个元素.前两个步骤之后的步骤不会影响最后两个元素.第一个x之后的步骤不会影响最后的x个元素.所以在那时你可以停止 - 数组的顶部包含统一随机选择的数据.数组的底部包含一些随机元素,但是你得到的排列不是均匀分布的.

当然这意味着你已经破坏了输入数组 - 如果这意味着你需要在启动前获取它的副本,并且x与y相比较小,那么复制整个数组效率不高.请注意,如果您将来要使用它进一步选择,那么它有点随机顺序并不重要,您可以再次使用它.因此,如果您多次进行选择,则可以在开始时只进行一次复制,并分摊成本.