蓄水池算法

题目:给出一个数据流,这个数据流的长度很大或者未知。并且对该数据流中数据只能访问一次。请写出一个随机选择算法,使得数据流中所有数据被选中的概率相等。

抽象:从n中取出k个数,n未知大小,保证最后n中每个元素被抽取的概率一样为k/n。

做法:假设我们从3个数{1,2,3}中取一个数,那么就要求每个数被抽取的概率为1/3,我们先读取前2个数{1,2},我们以1/2的概率选取其中一个数,加入选择{1},接下来读取数字{3},因为要求每个数被选取的概率为1/3,因此我们以1/3的概率选取数字{3},2/3的概率选取数字{1},那么最终数字1被选取的概率是2/3 * 1/2 = 1/3,同理数字{2}被选取的概率也是1/3。

将上述做法n个数选择1个数,每次要读取第n个数的时候,以1/n的概率保留该数,以(n-1)/n的概率保留前面n-1个数选取出来的1个数。

再推广到从n个数中选取k个数,假设读取到第n个数时(n>=k),以k/n的概率保留概述,以(n-k)/n的概率保留前n-1个中选取出来的k个数。

证明:使用上述步骤,从n中读取k个数,在读取n个元素后,n中每一个被保留下来的概率都是k/n。假设n = k + i,那么算法证明的就是第i轮选取中,前k+i个数每个数被保留的概率为k/(k+i),其中( 0 <= i <= n - k)。
用数学归纳法来证明:

当i=0是,每个数字被选取的概率为k/(k+0)=1,正确;
假设当i-1轮时,结论成立,即前k+i-1中每个数被保留的概率为k/(k+i-1);
第i轮,因为我们以k/(k+i)的概率选取第k+i个数,因此其概率为k/(k+i),正确;对于前k+i-1个数中的x,其被保留的概率由两部分组成:
①:第k+i个数没有被选取到,则x被选取的概率是:i/(k+i) * k/(k+i-1),其中k/(k+i-1)是2中假设的条件,即x在前k+i-1中被保留的概率;
②:第k+i个数被选取到,要替换前k+i-1中的数,那么x不被替换的概率是:k/(k+i) * k/(k+i-1) * (k-1)/k,k/(k+i-1)同①,k-1/k是指,在被选取为k个数之后,不被替换的概率。
因此,总概率为(i/(k+i) * k/(k+i-1)) + (k/(k+i) * k/(k+i-1) * (k-1)/k) = (k/(k+i-1)) * (i/(k+i) + (k-1)/(k+i)) = k/k+i;
得证。

具体算法步骤:

从n个数读取前k个数,保存在集合A中;
从第i个数开始(k<=i<=n),每次以k/i的概率选择是否保留概述,若保留,将随机替换k中任一数;
重复2,直到结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值