【发布时间】:2012-01-20 22:43:14
【问题描述】:
从 Steven Skiena 的算法设计手册中得到这个问题。
需要从具有n个数的给定集合S中选择k个(给定值)个数来形成子集S',使得每个数的选择概率相等(k/n)。 n 是未知的(我正在考虑将 S 作为此链接列表)。 同样,我们只能通过集合S。
【问题讨论】:
-
我认为问题是不同的,因为 n 是未知的。
标签: algorithm random numbers set
从 Steven Skiena 的算法设计手册中得到这个问题。
需要从具有n个数的给定集合S中选择k个(给定值)个数来形成子集S',使得每个数的选择概率相等(k/n)。 n 是未知的(我正在考虑将 S 作为此链接列表)。 同样,我们只能通过集合S。
【问题讨论】:
标签: algorithm random numbers set
你应该选择一个能够真正模拟真实活动的算法“从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
【讨论】:
当 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
【讨论】:
类似的东西
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 以此类推
【讨论】: