昨天面试,面试官问了我一道这样的题,没有回答出来,现在来总结一下。
Sampling 蓄水池抽样 主要是用来解决等概率选取问题,如果给你一个数组的数据,但是不知道的他的长度,而且每个数据只能访问一次,也就是说你没法通过遍历得到他的长度,也就不能用rand随机获取数据了,这样我们就要用到Sampling算法了
我总共总结了两个问题:1,从一组未知长度的数据里面随机等概率选取一个数?
2,从一组未知长度的数据里面随机等概率选取k个数?
这两个问题看起来很类似
我们先解决问题一: 由于不知道数组的长度,我们只能从一个i=1,2,3....依次选取,所以选取时的概率只能居于局部的概率,如果选择这个概率,是这个概率在整体上也和其他数据选取是等概率的呢? 先看下面方法,然后在证明
(1) 对于第n个数,被选取的概率为1/n ,如:第一个数 1/1,第二个数 1/2,第三个数,1/3.....
数学归纳法证明:
(1) 当n=1 时,被选中的概率 1/n=1,结果成立
(2) 假设当n=k时,被选中的概率为 1/k,则前 k-1个数被选中的概率也为 1/k
(3)证明 n=k+1时,结论仍然成立
注:如果算前k-1个数,每个数被选取的概率呢,很简单。假如i<k,这个概率就等于第i个数被选取的概率1/i *后面未被选取的概率
p=1/i *i/i+1 * i+1/i+2 *i+2/i+3 ....*n-2/n-1 *n-1/n=1/n
有上面注解可知,当n=k+1时,p=1/k+1,所以结论成立,证必。
第二个问题:从未知长度的数组里面等概率选取k 个元素
方法其实类似,如下
(1) 先选取前K个元素拿出来,然后对k+1个元素,选取的概率为 k/k+1,k+2个元素选取的概率为k/k+2;
怎样保证选取的都是等概率的呢
数学归纳法证明:
(1) 当 n=k+1的时候,第k+1个元素被选中的概率为k/k+1,显然 前k个元素的被选取的概率也为k/k+1
(2) 当 n=j的时候(j>k+1),结论成立,即 第j个元素被选中的概率为j/j+1,则 其余前j的每个元素被选取的概率为k/j+1
(3) 证明n=j+1的时候,结论仍然成立
注:当n=j+1时,如何求前j个元素,每个元素 t 被选取的概率呢,这个有两种条件:1,当前t个被选取的概率 2,未被后面元素替换的概率,
所以P=当前t被选取的概率*未被后面元素替换的概率 。当前被选取的概率 k/t ; 未被后面元素替换的概率 (1-1/k *k/t+1)* (1-1/k*k/t+2).......=t/t+1 *t+1/t+2*........*n-2/n-1*n-1/n=t/n;
所以P=k/t *t/n=k/n=k/j+1;
所以由注解得,上述结论得证