`

【编程珠玑】第十二章 取样问题

 
阅读更多

一,概述

问题描述:如何生成0~n-1内的m个随机整数(不重复

需求:按序输出,并且保证每个子集被选中的可能性相等。

1)给出下面代码


其中for循环保证 按序输出,rand()%(n-i) 保证输出概率符合要求。

算法时间复杂度 O(n)

2)非常规求法:

将n个数写到大小相等的纸片上,摇匀。然后取出m个纸片,按序输出m个纸片


3)解决算法时间复杂度问题,提出以下优化方案

给定一个集合S,每次插入一个元素。插入之前检查S中个数是否达到m,且随机数在不在m中。


C++模板插入操作在O(logm)时间内完成,而遍历集合需要O(m)时间。所以完整程序需要O(mlogm)时间

4)生成随机数的另一种方式:把包含0 - n-1的数组顺序打乱,然后把前m个元素输出。

更好的方式是,我们只需要打乱前m个元素,然后排序输出。

或者生成大于n个1 - n范围的随机数,然后去掉重复的,输出前面的m个元素


二,习题

1)


2)选择的m子集的概率相等,如何做?

在1 - n范围内随机选择一个数,然后其后的m-1 个数为所选择的子集(有可能到头,然后从0开始)


3)

当m < n/2时,

总共试了k次,则前面k-1次找到的数都是在集合中,那么只有第k次不在里面,那么概率

p = (m/n)^(k-1) * (n-m)/n

那么期望是 连加 k = 1至无穷大,根据二项式分布可知,期望等于

n/(n-m) < 2

从而可知得证

4)参考算法导论中文版64页。

搜集n张随机赠送的赠券,需要多少次? nlogn次


7)先输出再递归,改成先递归再输出

9)给出一个算法,在最坏情况下只使用m个随机数。而不用丢弃已经生成的随机数



10)问题:如何随机从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)


【说明】:当选中第2行,从第3行开始修改概率,并将第2行排除在外,继续扫描,这样能保证在剩下的5个数中仍然以等概率抽取其中的一个。

11)这个题看似很复杂,其实很简单。只需要关注1,2,3如何输出即可。要想获胜,只需要1,2先输出,三个数的全排列中这种情况有2种。所以获胜概率为2/6

=1/3

分享到:
评论

相关推荐

    编程珠玑源码下载编程珠玑书后源代码

    编程珠玑书后源代码编程珠玑书后源代码编程珠玑书后源代码编程珠玑书后源代码编程珠玑书后源代码编程珠玑书后源代码

    编程珠玑 编程珠玑 编程珠玑 编程

    我觉得不错,和大家分享! 编程珠玑 编程珠玑 编程珠玑

    编程珠玑编程珠玑

    编程珠玑编程珠玑

    编程珠玑之第二章questionC 测试数据

    本资源只是“编程珠玑之第二章questionC: 求变位词问题”的简单的测试数据。

    编程珠玑 编程珠玑续

    编程珠玑和编程珠玑续两本,上传赚点分,填充填充填充

    编程珠玑(续)

    《编程珠玑(续)》是计算机科学方面的经典名著《编程珠玑》的姊妹篇,讲述了对于程序员有共性的知识。书中涵盖了程序员操纵程序的技术、程序员取舍的技巧、输入和输出设计以及算法示例,这些内容组成一个有机的整体,...

    编程珠玑续本

    编程珠玑续、编程珠玑续本、编程珠玑续本、编程珠玑续本

    编程珠玑 第二版 修订版

    第12章 取样问题 119 12.1 问题 119 12.2 一种解决方案 120 12.3 设计空间 121 12.4 原理 123 12.5 习题 124 12.6 深入阅读 125 第13章 搜索 127 13.1 接口 127 13.2 线性结构 129 13.3 二分搜索树 132 ...

    编程珠玑及其源码

    为此,本书给出了一些精心设计的有趣而且颇具指导意义的程序,这些程序能够为那些复杂的编程问题提供清晰而且完备的解决思路,书中还充满了对实用程序设计技巧及基本设计原则的清晰而睿智的描述。

    编程珠玑.pdf

    第12章 对调查的研究 113 12.1 有关民意调查的问题 113 12.2 语言 114 12.3 图片 117 12.4 原理 119 12.5 习题 120 第四部分 算 法 第13章 绝妙的取样 123 13.1 取样算法一瞥 123 13.2 Floyd算法 124 13.3 随机排列 ...

    《编程珠玑》源代码

    《编程珠玑》第一版是我早期职业生涯中阅读过的对我影响较大的书籍之一,在书中首次接触到的很多观点都让我长期受益。作者在这一版本中做了重要更新。新增加的很多例子让我耳目一新。 ——Steve McConnell,《代码...

    编程珠玑II(编程珠玑·续) 扫描版6.56M pdf格式

    编程珠玑II(编程珠玑·续) 扫描版6.56M pdf格式

    编程珠玑习题集锦

    书的内容围绕程序设计人员面对的一系列实际问题展开。作者Jon Bentley 以其独有的洞察力和创造力,引导读者理解这些问题并学会解决方法,而这些正是程序员实际编程...《编程珠玑(第2版)》是计算机科学方面的经典名著。

    编程珠玑总结笔记

    编程珠玑是一本提升coding能力不可多得的好书,看书时,可以结合这个笔记,突出重点。

    编程珠玑+续

    编程珠玑+续

    编程珠玑高清pdf

    这本书是《编程珠玑》高清pdf,如有侵权请告知。

    编程珠玑(第二版)答案

    编程珠玑(第二版)答案

    《编程珠玑》读书笔记

    《编程珠玑》读书笔记

Global site tag (gtag.js) - Google Analytics