问题描述
给定一个无限的数据流,要求随机取出 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)。
综上所述,得证。
