【问题】从长度未知的数据流中取k个数,求一个算法来保证最后每个元素被取到的概率都为k/n。
例子:淘宝双十一,12点整秒杀雅诗兰黛小蓝瓶,从若干个用户里选1000个人,并保证在1秒以内进来的用户,选取的概率都均等。这里长度未知的数就等同于12点时的秒杀用户,而选取的k个数就等同于1000个用户;并且无论参与总人数n是多大,每个人被选到的概率均为1000/n
【算法】
1、数据流中的头k个数固定选中,并设为头k个位置。
2、从后面顺序号为i=k+1起的每一数,它都以概率k/i被选中,并以1/k的概率替换掉头k个数里的其中一个。
该算法能保证数据流结束时,每个数均以k/n的概率被选中
【证明】
由于,第i个数被选中的概率=k/i;
同时,第i个数被第i+1个数挤出位置的概率
=第i+1个数被选中的概率 * 第i+1个数恰好把第i个数挤出位置的概率
=k/(i+1) * 1/k =1/(i+1)
因此,第i个数没被第i+1个数挤出位置的概率
=1 - 1/(i+1)
= i/(i+1)
因此,数据流中第i个数被最终保留在k个位置里的概率=
第i个数被选中的概率 * 第i个数没被第i+1个数挤出位置的概率 * 第i个数没被第i+2个数挤出位置的概率 *...* 第i个数没被最后一个数挤出位置的概率
=k/i * i/(i+1) * (i+1)/(i+2) * ... * (n-1)/n
=k/n....1)
由于以上推导中i是任意大于k的值,因此当i>k时原问题得证。
同理可得,j<k时,即最先放进去的k个数里,每个最终保留的概率为
=第j(j<=k)个数被选中的概率 * 第j个数没被第k+1个数挤出位置的概率 * 第j个数没被第k+2个数挤出位置的概率 *...* 第j个数没被最后一个数挤出位置的概率
=1 * k/(k+1) * (k+1)/(k+2) * ... * (n-1)/n
= k/n....2)
因此,当i<=k时原问题得证。
联立1),2),原问题得证。