蓄水池抽样
今天又在“待字闺中”上看到将蓄水池抽样的题,想起一年多之前小光找工作的时候考过我这个。这里做个备忘。
转自:https://www.guokr.com/blog/745588/
题目要求:
从个元素中随机抽取个元素,但的个数无法事先确定。
在实际应用中,往往会遇到很大数据流的情况。因此,我们无法先保存整个数据流然后再从中选取,而是期望有一种将数据流遍历一遍就得到所选取的元素,并且保证得到的元素是随机的算法。
蓄水池抽样算法:
- 先选取n个元素中的前k个元素,保存在集合A中;
- 从第 j (k+1 <= j <= n) 个元素开始,每次先以概率选择是否让第 j 个元素留下。若第 j 个元素存活,则从A中随机选择一个元素并用该元素 j 替换它;否则直接淘汰该元素 j ;
- 重复1和2,直到结束。最后集合 A 中剩下的就是保证随机抽取的 k 个元素。
蓄水池抽样算法正确性证明:
为了证明该算法的正确性,我们要保证算法结束后,原n个元素每一个最后存活下来的概率都是 k/n(因为从 n 个元素中随机抽取k个元素,每个元素被抽中的概率都是k/n)。形式化地,我们要证明的结论是:在算法的第 i(0<= i <= n-k) 轮,前 k+i个元素每一个存活下来的概率都是 k/(k+i)。
----------------------------------------
利用数学归纳法:
- 当 i=0 时,结论显然成立。
- 当 0< i <= n-k 时,根据算法,元素 k+i 存活的概率为 k/(k+i)。而对于元素 l (1<= l < k+i),有两种情况会使其存活下来:要么元素 k+i 直接被淘汰;要么元素k+i 留下,但是没有替换掉元素 l 。由归纳假设, i-1 时结论成立,故元素 l 存活的概率为,得证。
----------------------------------------
值得一提的是,在实际中,常常需要通过一次遍历,从大量的个元素中随机选取一个。这其实是蓄水池抽样在时的特例。