[转]文档的行数未知,怎样在概率控制下,选择输出每行
2015-06-16 18:00
239 查看
问题:如何随机从n个对象中选择一个对象,这n个对象是按序排列的,但是在此之前你并不知道n的值?
具体些说,在事先并不知道行数的情况下,如何读一个文本文件,随机选择并输出一行?
解答:我们总是选择第一行,并使用二分之一的概率选择第二行,使用三分之一的概率选择第三行,以此类推。在该过程结束的时候,每一行具有相同的选中概率(1/n,其中n是文件的总行数):
i = 0 while more input lineswith probability 1.0/++ichoice = this input line //如果前面做了选择,并不会break,而是直到最后一个为止。print choice
这里比较有些疑惑的是第一行:总是选第一行 为什么概率还是1/n?
概率=1*(1/2)(2/3)(3/4)……(n-1/n) =1/n
证明:当做第i步选择(选择第i行)时,选择该行的概率为1/i,则不选择的概率为(i-1)/i对于一篇有n行的文档,现需证明最终选定第i行的概率为1/n。
当最终选择第i行,前(i-1)步的选择对最终结果不会产生影响,第i步选择的概率为1/i,即选择第i行,第(i+1~n)步中均采取不选择的动作,即对于任意j(i+1<=j<=n),当前步的概率为(j-1)/j,那么最终的概率为:(1/i)((i)/(i+1))…*((n-1)/n) = 1/n
以一篇只有6行的文档为例,最终选择第2行的概率为:1/2*(2/3)(3/4)(4/5)*(5/6) = 1/6
扩展:原问题可简化为:如何从n个有序对象中等概率地任意抽取1个,简记为sample(n,1),其中n未知;
若将该问题改为:如何从n个有序对象中等概率地任意抽取m个,简记为sample(n,m),其中n未知;
分析:若n已知,sample(n,m)是普通的抽样问题;当n未知时,可否根据上述算法进行相应的转化求解?
解决方案:将sample(n,m)问题转化为m个sample(n*,1)问题,更具体一点是,转化为sample(n,1);sample(n-1,1);sample(n-2,1)….;sample(n-m+1,1)问题。仍然以一篇6行文档为例,任取其中2行,做法如下:第一遍,以如下概率选中一行:1(1) 2(1/2) 3(1/3) 4(1/4) 5(1/5) 6(1/6)假设选中第2行,接着概率修改如下:3(1) 4(1/2) 5(1/3) 6(1/4) 1(1/5)
具体些说,在事先并不知道行数的情况下,如何读一个文本文件,随机选择并输出一行?
解答:我们总是选择第一行,并使用二分之一的概率选择第二行,使用三分之一的概率选择第三行,以此类推。在该过程结束的时候,每一行具有相同的选中概率(1/n,其中n是文件的总行数):
i = 0 while more input lineswith probability 1.0/++ichoice = this input line //如果前面做了选择,并不会break,而是直到最后一个为止。print choice
这里比较有些疑惑的是第一行:总是选第一行 为什么概率还是1/n?
概率=1*(1/2)(2/3)(3/4)……(n-1/n) =1/n
证明:当做第i步选择(选择第i行)时,选择该行的概率为1/i,则不选择的概率为(i-1)/i对于一篇有n行的文档,现需证明最终选定第i行的概率为1/n。
当最终选择第i行,前(i-1)步的选择对最终结果不会产生影响,第i步选择的概率为1/i,即选择第i行,第(i+1~n)步中均采取不选择的动作,即对于任意j(i+1<=j<=n),当前步的概率为(j-1)/j,那么最终的概率为:(1/i)((i)/(i+1))…*((n-1)/n) = 1/n
以一篇只有6行的文档为例,最终选择第2行的概率为:1/2*(2/3)(3/4)(4/5)*(5/6) = 1/6
扩展:原问题可简化为:如何从n个有序对象中等概率地任意抽取1个,简记为sample(n,1),其中n未知;
若将该问题改为:如何从n个有序对象中等概率地任意抽取m个,简记为sample(n,m),其中n未知;
分析:若n已知,sample(n,m)是普通的抽样问题;当n未知时,可否根据上述算法进行相应的转化求解?
解决方案:将sample(n,m)问题转化为m个sample(n*,1)问题,更具体一点是,转化为sample(n,1);sample(n-1,1);sample(n-2,1)….;sample(n-m+1,1)问题。仍然以一篇6行文档为例,任取其中2行,做法如下:第一遍,以如下概率选中一行:1(1) 2(1/2) 3(1/3) 4(1/4) 5(1/5) 6(1/6)假设选中第2行,接着概率修改如下:3(1) 4(1/2) 5(1/3) 6(1/4) 1(1/5)
相关文章推荐
- 初学Java的一些疑问
- Node.js Express 使用 在Mac电脑
- 137在搜索框中实现下拉列表效果(扩展知识:表格视图数据源为空数据时显示提示信息)
- float的内存布局
- Solr-3-Solr Cloud分布式安装
- c++ Builder 死机解决方法
- C++类中:作用
- virtio-netdev 发送数据包
- list,arraylist,哈希表,字典,datatable的selct等等用法
- C++ 自定义控件的移植(将在其它程序中设计的自定义控件,移植到现在的系统中)
- Eclipse下printf和scanf的运行顺序问题
- 第二题
- Solr-2-单机安装
- 动态往div里添加img
- [翻译]Swift编程语言——属性
- C++程序中获取不带文件路径和后缀的文件名
- Java中.class文件的结构
- Git Cheat Sheet Chinese
- UIView
- Java中printwriter类的用法