您的位置:首页 > 其它

蓄水池抽样问题

2013-10-18 22:14 141 查看
部分内容转自http://handspeaker.iteye.com/blog/1167092

/article/1358256.html

这种应用的场景一般是数据流的情况下,由于数据只能被读取一次,而且数据量很大,并不能全部保存,因此数据量N是无法在抽样开始时确定的;但又要保持随机性,于是有了这个问题。所以搜索网站有时候会问这样的问题。

此类型的算法题有:谷歌面试题:给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字)
。如何才能从这个无穷尽的流中随机的选取 1000 个关键字?

这里的核心问题就是“随机”,怎么才能是随机的抽取元素呢?我们设想,买彩票的时候,由于所有彩票的中奖概率都是一样的,所以我们才是“随机的”买彩票。那么要使抽取数据也随机,必须使每一个数据被抽样出来的概率都一样。

【解决】

解决方案就是蓄水库抽样(reservoid sampling)。主要思想就是保持一个集合(这个集合中的每个数字出现),作为蓄水池,依次遍历所有数据的时候以一定概率替换这个蓄水池中的数字。

其伪代码如下:

Init : a reservoir with the size: k

for i= k+1 to N

M=random(1, i);

if( M < k)

SWAP the Mth value and ith value

end for

证明:每次选择时,蓄水池出现每个数的概率为k/(已选过的数字数目)。用归纳法证明:

1.当 i <= k 时,第i个数出现在蓄水池中的概率为1.

2.假设当选到第i个数时,前i个数出现在蓄水池中的概率为k/i

3.当i+1个数时,第i+1个数出现在蓄水池中的概率为这个数被选中替换蓄水池中的数的概率,也就是k/i+1;

前i个数出现在蓄水池中的概率为,前i次替换中出现在蓄水池中(事件A)且第i+1次没有被替换的概率(事件B).p = P(A)*P(B);

P(A) = k/i,根据假设;P(B) = P(第i+1个数没被选中)+P(第i+1个数被选中)*P(当前数字不是被替换的数字)= (1- k/(i+1)) + k/(i+1) * (k-1)/k = i/(i+1);

所以p = k/i * i/(i+1) = k/(i+1)

故证明成立

同样的道理可以应用到类似的题目中,例如:

谷歌面试题:给定一个未知长度的整数流,如何随机选取一个数

方法:保存一个数作为蓄水池,对第i个数,用1/i的概率替换蓄水池中的那个数,最后得到随机数。利用这种方法,我们只需保存一个随机数,和迄今整数流的长度即可。所以可以处理任意长的整数流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: