【问题标题】:selection of numbers from a set with equal probability以相等的概率从集合中选择数字
【发布时间】:2012-01-20 22:43:14
【问题描述】:

从 Steven Skiena 的算法设计手册中得到这个问题。

需要从具有n个数的给定集合S中选择k个(给定值)个数来形成子集S',使得每个数的选择概率相等(k/n)。 n 是未知的(我正在考虑将 S 作为此链接列表)。 同样,我们只能通过集合S。

【问题讨论】:

标签: algorithm random numbers set


【解决方案1】:

你应该选择一个能够真正模拟真实活动的算法“从n个数字中随机选择k个数字”。你的算法应该有两个属性

(1) 最后必须返回 k 个数字。

(2) 必须真实地模拟目标活动的属性:每个数字都以概率 k/n 被选择。

Oboroks answer is wrong because it hasnt 第一个属性。

for i = 0 to n
randomly choose an integer number between [1,n-i+1]
if [randomValue <= (k - S'.size)/(S.size - i + 1)] then
    S'.add(S[i])

通过上述选择方案,每个数字以概率 k/n 选择。您可以通过以下等式证明:

https://www.facebook.com/photo.php?fbid=677984275648191&l=7cafe5d468

【讨论】:

    【解决方案2】:

    n 未知时,您宁愿需要一个在线算法来进行所谓的水库采样

    这里提供了很好的解释和证明草图http://propersubset.com/2010/04/choosing-random-elements.html

    我的意思是这个算法用 Python 实现(取自上面的链接)

    import random
    def random_subset( iterator, K ):
        result = []
        N = 0
    
        for item in iterator:
            N += 1
            if len( result ) < K:
                result.append( item )
            else:
                s = int(random.random() * N)
                if s < K:
                    result[ s ] = item
    
        return result
    

    【讨论】:

      【解决方案3】:

      类似的东西

      for elem in S
        if random() < (k - S'.size)/S.size // This is float division
          S'.add(elem)
      

      k/n 的概率选择第一个元素,以(n-k)/n * k/(n-1) + k/n * (k-1)/(n-1) 减少到k/n 以此类推

      【讨论】:

      • 根据您提供的公式,您应该考虑 elem 的索引 i (从 1 开始),因此具有 random()
      • 如果 S.size 未知,则此答案不起作用,这是原始问题中给出的条件
      • 没错。我无法删除,因为它已被接受,但似乎另一个答案是正确的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-22
      • 2017-12-12
      • 2017-11-23
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多