水库采样算法

时间:2013-01-20 21:23:03

标签: java algorithm random-sample

我想了解油藏采样算法,其中我们从给定的S元素集合中选择k个元素,使得k <= S。

在wiki上给出的算法中:

array R[k];    // result
integer i, j;

 // fill the reservoir array

for each i in 1 to k do
    R[i] := S[i]
done;

// replace elements with gradually decreasing probability

for each i in k+1 to length(S) do
    j := random(1, i);   // important: inclusive range
    if j <= k then
        R[j] := S[i]
    fi
done

如果我理解正确,我们首先从集合中选择k个元素,然后连续解析S的i个元素,在1到i的范围内生成随机的no j,并用S [i]替换元素j。

如果要采样的集合K非常大,看起来很好,但如果我想从随机的无限大小(至少未知大小)的链表中选择1个元素,我将如何使用此算法执行此操作...?

2 个答案:

答案 0 :(得分:3)

水库采样算法适用于任何大小的链表,即使是预先知道其长度的链表。事实上,水库采样的主要卖点之一是它适用于预先不知道其大小的数据流。

如果你设置k = 1,然后运行正常的油藏采样算法,那么你应该从列表中正确获得一个随机的元素。

希望这有帮助!

答案 1 :(得分:0)

我已经实现了一个不同的算法来解决这个问题,这是我的代码

static char[] solution2(String stream, int K) {
    HashSet<Integer> set = new HashSet();
    char[] list = new char[K];
    stream = stream.concat(stream2);
    Random ran = new Random();
    for (int i = 0; i < K; i++) {
        int y = ran.nextInt(stream.length());
        if (set.add(y)) {
            list[i] = stream.charAt(y);
        } else {
            i--; //skip this iteration since its duplicate number
        }
    }
    return list;
}

不是迭代所有流值,只需选择随机值J并从流中获取N [J]。