蓄水池算法

从数据流中等概率抽取一定的结果。

  1. 数据总量为n,需要取k个
  2. 构建一个k数组,前k个元素放入数组中
  3. 从第k+1个开始,k/i(i为当前的数量)的概率决定是否留在数组中,随机挑一个移出队列。

证明:

  1. 前k个数据。第k+1步被替换的概率:

$$
\frac{k}{k+1}\times \frac{1}{k}=\frac{1}{k+1}
$$

保留的概率:
$$
1-\frac{1}{k+1}=\frac{k}{k+1}
$$
一直到第n个,保留的概率:
$$
1\times \frac{k}{k+1}\times\frac{k+1}{k+2}\times\frac{k+2}{k+3}\times…\times\frac{n-1}{n}=\frac{k}{n}
$$

  1. k后面的数据,i

    被替换的概率:
    $$
    1-\frac{k}{i+1}\times\frac{1}{k}=\frac{i}{i+1}
    $$
    一直到最后一个:
    $$
    \frac{k}{i}\times\frac{i}{i+1}\times…\times\frac{n-1}{n}=\frac{k}{n}
    $$

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Sampling{
    public static int[] sampling(int K, int N){
    int[] arr = new int[N];
    for(int i = 0; i < N; i++){
    arr[i] = i;
    }

    int[] pool = new int[K];
    for(int i = 0; i < K; i++){
    pool[i] = arr[i];
    }

    Random random = new Random();
    for(int i = K; i < N; i++){
    int index = random.nextInt(i + 1);
    if(index < K){
    pool[index] = arr[i];
    }
    }
    return pool;
    }
    }