#题目:
水塘抽样是一组解决数据流取样的方法, 有很多的变种. 它适用的问题有如下特点:
1.对象为无法在内存中放下的数据, 如不间断数据流, 或者巨大的文件, 数组等.
2.样本集的大小为k, 并且要求每个样本的取样概率相等.
3.取样概率可以通过添加权重(weight)来改变取样概率.
一般(无weight)水塘抽样的每个样本的取样概率为: k/(n+1)
水塘抽样的算法实现非常简单, 而且证明简练. 算法如下:
1.预设数组A, 大小为k. 先取样k个元素. 放入A中.
2.从k+1元素开始, 每次取得随机数r, 范围为(0,k+1).
3.如果r <= k, A[r] = S[k+1], S是当前数据流.
public int[] sampling(InputStreamReader in, int k) throws IOException {
int[] res = new int[k];
int cur = 0;
Random random = new Random();
while (in.ready()) {
int data = in.read();
if (cur<k){
res[cur] = data;
}
else {
int r = random.nextInt(k+1);
if (r < k)
res[r] = data;
}
cur++;
}
return res;
}
最后再说一句:考虑一下这个问题,假设我们不知道集合S的大小,如何随机的取出一个元素
这么思考,这就是水塘问题:k=1的特例情况