给定一个数组,数组大小N,随机选择K个样品。
如果K比较小,可以随机生成K个在[0,N)之间的不重复的数,然后以这K个数作为index在原始数组中选择样品。
但是如果K比较大,比如N=100000000,K=10000000,那么如何快速生成K个限定范围的不重复的随机数?
可以构造一个大小为N的循环链表,初始化一个指针指向起点。随机生成一个数r,把指针往后移动r个位置,选择这个数作为样品,删除这个节点,并且把指针往后移动一位。重复以上步骤K次得到所有样品。
但是上面的方法空间复杂度是O(N),并且如果N的大小未知呢?
这里是从wikipedia找到的伪代码
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