蓄水池算法要解决的问题就是在不知道流入数据量多少的情况下,依旧可以随机从这些数中选取K个,乍一听好神奇,其实分析一下背后的概率知识,思想还是很简单的,相信看完我的介绍和证明,你也会觉得很简单。
假设要求随机选择K个元素,假设一共流入的元素有n个。
首先数组a[0...k-1]表示最后返回的结果,最开始流入的k个元素依次放入a[0...k-1]中;
那么从第k+1到第n个元素每一次都有可能把数组a中的元素踢走换成自己,假设现在流入了第i个元素,搞个随机数生成器,pos=rand()%i,如果pos<k,那么就把这个元素放到pos这个位置上,把以前这个位置上的元素剔除。
最后,返回数组a就可以了,就是概率相等的k个元素。
下面来证明所有的元素都是等概率的:
首先,来看第1~k个元素:
最后存在的概率是:
1*[k/(k+1)]*[(k+1)/(k+2)]*[(k+2)*(k+3)]*...*[(n-1)/n]=k/n
来分析一下,前k个元素,以第一个举例,初始选中概率为1,后面每增加一个元素不能把第一个元素替换掉的概率依次是[k/(k+1)],[(k+1)/(k+2)],[(k+2)*(k+3)]。。。
这样到最后一个元素,分子分母相约,得到第一个元素存在的概率是k/n;
再看第k+1~n个元素:
从第k+1开始,k+1<= i <=n,现在有i-1个元素,进来一个元素时选中它的概率是k/i,而后面的元素没有把它替换掉的概率是:
[i/(i+1)],[(i+1)/(i+2)],[(i+2)*(i+3)] ... [(n-1)/n]
最后得到概率是[k/i]*[i/(i+1)]*[(i+1)/(i+2)]*[(i+2)*(i+3)]* ... *[(n-1)/n]=k/n
综上,得到蓄水池算法得到k个元素都是等概率的。