1、水塘抽样解决的问题
对一个数量未知的样本,希望只经过一次遍历就完成随机抽样,即时间复杂度O(n)。因为样本数量未知,因此就不能通过random函数直接随机抽样。
2、水塘抽样的逻辑
希望在n个样本中随机抽取k个数据。即每个数据被抽取的概率为k/n。
首先我们创建一个k个成员的数组out,用来存放预期抽出的样本。
(1)当k>=n时,每一个样本被抽取的概率都为100%。因此都可以直接放入数组out。
(2)当k<n时,对于第n个样本,我们希望其被抽取的概率为k/n,因此我们需要设计出k/n的概率将其放入数组out(创建一个0-n之间的随机数,判断其大于k的概率就是k/n)。同时out中会有一个数据会被踢出。
(3)当k<n时,对于数组out中已存的数据,其在上一轮被留下的概率为k/(n-1) ,这一轮发生不抽样的概率(n-k)/n,发生抽样的概率为k/n。发生抽样不被抽走的概率为(k-1)/k。因此其被抽取的概率为:
上一轮抽中的概率 * (不发生抽样的概率 + 发生抽样的概率 * 不被抽走的概率)
k/(n-1) * ((n-k)/n + k/n * (k-1)/k) = k/n
概率也为k/n
3、代码实现
public class PoolSimple {
public static void main(String[] arg