我想了解油藏采样算法,其中我们从给定的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个元素,我将如何使用此算法执行此操作...?
答案 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]。