蓄水池抽样 分类: 算法
2013-04-21 13:46
302 查看
蓄水池抽样
分类: 算法2012-09-1109:03 116人阅读 评论(2) 收藏 举报
randominput编程扩展filec
/article/7009471.html
问题起源于编程珠玑Column
12中的题目10,其描述如下:
How
could you select one of n objects at random, where you see the objects sequentially but you do not know the value of n beforehand? For concreteness, how would you read a text file, and select and print one random line, when you don’t know the number of lines
in advance?
问题定义可以简化如下:在不知道文件总行数的情况下,如何从文件中随机的抽取一行?
首先想到的是我们做过类似的题目吗?当然,在知道文件行数的情况下,我们可以很容易的用C运行库的rand函数随机的获得一个行数,从而随机的取出一行,但是,当前的情况是不知道行数,这样如何求呢?我们需要一个概念来帮助我们做出猜想,来使得对每一行取出的概率相等,也即随机。这个概念即蓄水池抽样(Reservoir
Sampling)。
有了这个概念,我们便有了这样一个解决方案:定义取出的行号为choice,第一次直接以第一行作为取出行 choice ,而后第二次以二分之一概率决定是否用第二行替换 choice ,第三次以三分之一的概率决定是否以第三行替换 choice ……,以此类推,可用伪代码描述如下:
i = 0
while more input lines
with probability 1.0/++i
choice = this input line
print choice
这种方法的巧妙之处在于成功的构造出了一种方式使得最后可以证明对每一行的取出概率都为1/n(其中n为当前扫描到的文件行数),换句话说对每一行取出的概率均相等,也即完成了随机的选取。
证明如下:
回顾这个问题,我们可以对其进行扩展,即如何从未知或者很大样本空间随机地取k个数?
类比下即可得到答案,即先把前k个数放入蓄水池,对第k+1,我们以k/(k+1)概率决定是否要把它换入蓄水池,换入时随机的选取一个作为替换项,这样一直做下去,对于任意的样本空间n,对每个数的选取概率都为k/n。也就是说对每个数选取概率相等。
伪代码:
Init : a reservoir with the size: k
for i= k+1 to N
M=random(1, i);
if( M < k)
SWAP the Mth value and ith value
end for
证明如下:
蓄水池抽样问题是一类问题,在这里总结一下,并由衷的感叹这种方法之巧妙,不过对于这种思想产生的源头还是发觉不够,如果能够知道为什么以及怎么样想到这个解决方法的,定会更加有意义。
相关文章推荐
- 双端队列、随机队列、蓄水池抽样算法
- 大数据算法MOOC笔记3:水库抽样Reservoir Sampling(蓄水池问题)
- 海量数据处理之蓄水池抽样算法
- 随机抽样算法:蓄水池抽样
- 蓄水池抽样算法
- 蓄水池抽样算法 Leetcode 382
- 蓄水池抽样算法
- 蓄水池抽样算法 (Reservoir Sampling Algorithm)
- MySTL:蓄水池抽样算法
- Reservoir Sampling 蓄水池抽样算法,经典抽样
- 蓄水池(Reservoir_sampling)抽样算法简记
- 数据工程师必知算法:蓄水池抽样
- 蓄水池抽样算法 & 随机洗牌算法
- 算法学习之---蓄水池抽样问题
- Reservoir Sampling 蓄水池抽样算法,经典抽样
- LeetCode:382. Linked List Random Node(蓄水池抽样算法C++)
- 蓄水池抽样算法学习和应用
- 随机抽样——蓄水池抽样算法(Reservoir Sampling)
- Leetcode Linked List Random Node C++(蓄水池抽样算法)
- LeetCode:382 Linked List Random Node蓄水池抽样算法