问题描述
给定一个无限的数据流,要求随机取出 k
个数。也就是说当数据流有 N
个数据时,不论 N
为多少,每个数被取出的概率都为 k/N
算法
- 先取出前
k
个数; - 从第
k+1
开始,以k/i
的概率取出这个数,并随机替换掉之前已经取出的k
个数中的一个。
1 | Init a reservoir with the size k |
证明
使用归纳法进行证明,其中 i
表示当前到来的数据编号。
- 当
i==k+1
时,该数以k/(k+1)
被取出。当该数被取出时,需要替换前k
个数中的某个数,被替换的概率为k/(k+1) · 1/k = 1/(k+1)
,这个数被保留的概率即为1 - 被替换的概率 = 1 - 1/(k+1) = k/(k+1)
。 - 假设
i==p
时符合条件,即前p
个数都以k/p
的概率被取出。当i==p+1
时,该数被取出概率为k/(p+1)
。对于前p
个数,该数被取出要符合两个条件:之前被取出、没有被第p+1
的数替代。没有被第p+1
的数替代的概率 =1 - 被第 p+1
的数替换。因此总概率为k/p ·(1- k/(p+1)·1/k) = k/ (p+1)
。
综上所述,得证。