蓄水池抽样问题

来源:互联网 发布:linux 注释多行 编辑:程序博客网 时间:2024/05/01 08:17

题目:

微软电面问到的问题,前面提了一大堆背景,最后归结为一个问题,如何在连续的网络流量中,等概率随机抽取1个数据包。

分析:

参加电面时,还没看过蓄水池抽样问题,后来回来一搜,这就是典型的蓄水池抽样问题,不过当时自己也想到了一种解法,使用一个变量保存数据包,从1到i个数据包,每次遇到第i个数据包,以1/i的概率选取这个数据包,并且替换原来的数据包,这样到第n个数据包,我们能保证我们以1/n的概率选取这n个数据包中的1个。

证明:

加入第i个数据包到来,我们以1/i的概率选取这个数据包,显然,它的概率是符合的,那么第i-1个数据是不是也符合呢?我们假设第i-1次取数据包时,前面i-1个数据包以1/(i-1)的概率选取,那么第i-1个数据包被保留下来的概率是1-p(第i个数据包保存)再乘上p(1到i-1次选择被保存的概率),这里p(1到i-1次选择被保存的概率)就是假设的1/(i-1),那么第i次取包,前i-1个数据包被保存的概率是:

(1 - 1/i) * 1/(i - 1) = 1/i,说明前i-1个数据包的选取概率也是1/i;

由此进行归纳,可以得到最终结果。

扩展:

考虑蓄水池中抽取k个元素。

方法还是一样,假设前i次选择时,前i个数据包被选到水库的概率是k/i,那么第i+1次选择时,前面i个数据包保留在水库中的概率是

k/i * (1 - k/(i + 1) * 1/k) = k/(i + 1)

所以第i+1次选择,所有的数据包还是以k/(i + 1)的概率保存到水库中,得证。

伪代码如下:

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

总结:

蓄水池问题非常经典,而且非常实用,需要理解其中原理。

原创粉丝点击