1. 蓄水池的容积为1
(1)问题
如何随机从n个对象中选择一个对象,这n个对象是按序排列的,但是在此之前你不知道n的值?
(2)算法与证明
算法:我们先将第一个对象作为备选放入蓄水池,也就是说第一个对象被放入蓄水池的概率为1,以 1 / 2 1/2 1/2的概率选择第二个,以 1 / 3 1/3 1/3的概率选择第三个,以此类推,以 1 / m 1/m 1/m的概率选择第m个对象。当该过程结束时,每一个对象具有相同的选中概率,即 1 / n 1/n 1/n。
证明:第m个对象最终被选中的概率P=选择m的概率*其后面所有对象不被选择的概率,即
P = 1 m × ( m m + 1 × m + 1 m + 2 × ⋅ ⋅ ⋅ × n − 1 n ) = 1 n P=\frac{1}{m}\times(\frac{m}{m+1}\times\frac{m+1}{m+2}\times···\times\frac{n-1}{n})=\frac{1}{n} P=m1×(m+1m×m+2m+1×⋅⋅⋅×nn−1)=n1
由于这里处理的对象是以流的形式出现的,所以当第m个对象出现时,在已有的数据中选中第m个对象的概率为 1 m \frac{1}{m} m1,当第m+1个对象出现时没选中第m+1个对象的概率为 m m + 1 \frac{m}{m+1} m+1m,以此类推。
所以在实际问题的处理中,只需要对每个新增的对象按照 1 m \frac{1}{m} m1的概率来选择就好了。
(3)代码实现
假设我们要在n行的文本文件中随机选取一行,但事先不知道n为多少,则代码如下:
m = 0
s = null
for line in 文本文件:
m = m+1
r = (0,1)之间的随机数
if r < 1/m:
s = line
2.蓄水池的容积为m
(1)问题
如何随机从n个对象中选择m个对象,这n个对象是按序排列的,但是在此之前你不知道n的值?
(2)算法与证明
前m个对象被选中的概率为1,当我们读到第i-1行时(i-1大于m),我们假设前i-1个对象被选中的概率均为
m
i
−
1
\frac{m}{i-1}
i−1m,那么,当我们读到第i行的时候,前i-1行中每一行被选中的概率为上一次被选中的概率乘以这一次没有被选中的概率,即为
P
=
m
i
−
1
×
(
1
−
m
i
×
1
m
)
=
k
i
P=\frac{m}{i-1}\times(1-\frac{m}{i}\times\frac{1}{m})=\frac{k}{i}
P=i−1m×(1−im×m1)=ik
(3)代码
i = 0
s = []
for line in 文本文件:
i = i+1
if i <= m:
s.append(line)
else:
j = [1,i]之间的随机数
if j <= m:
s[j] = line