一些数据结构的思想(3)
- 随机函数发生器的设计
假设你希望以各1/2的概率输出0和1.你可以自由使用一个输出0或1的过程BIASED-RANDOM。它以概率p输出1,以概率1 - p输出0,其中 0 < p < 1,但是你并不知道p的值。给出一个利用BIASED-RANDOM作为子程序的算法,返回一个无偏向的结果,即以概率1/2返回0,以概率1/2返回1。作为p的函数,你的算法的期望运行时间是多少?
算法分析:
已知BIASED-RANDOM可产生0和1,那么 1 - BIASED-RANDOM也产生1和0,且以1 - p的概率输出1,以p的概率输出0。
如果我们将1 - BIASED-RANDOM看做另外一个函数发生器,和BIASED-RANDOM组合成对被调用,有以下结论:
调用结果 00 01 10 11
1的个数 0 1 1 2
出现概率 (1-p)*(1-p) (1-p)*(1-p) p*p p*(1-p)
那么,进行一次调用,出现1的个数的期望值为: 0 * (1-p)*(1-p) + 1 * (1-p)*(1-p) + 1 * p*p + 2 * p*(1-p) = 1。进行4次成对调用,则1的期望个数为4。为什么要调用4次呢?因为BIASED-RANDOM产生0的概率和 1 - BIASED-RANDOM产生1的概率相等;BIASED-RANDOM产生1的概率和 1 - BIASED-RANDOM产生0的概率相等,那么4次刚好覆盖了所有组合对(00,01,10,11),也可进行8次,16次等调用。当进行4次成对调用后,统计1出现的个数,若小于4次,则返回0;大于4次,则返回1(这里相当于将4次调用封装为了一个函数)。但有个问题,等于4次该返回0还是1呢?(因为1的可能次数为0至8)所以,可进行大量成对调用,以使单个现象可被忽略。如,进行1024次调用,统计1的个数,小于1024返回0,否则返回1。
- 随机概率发生器
题目:
已知一随机发生器,产生0的概率是p,产生1的概率是1-p,现在要你构造一个发生器,使得它构造0和1的概率均为1/2
解决方案:
这是随机概率发生器的典型题目。
由于需要产生1/2,而用1位0,或1位1无法产生等概率,因此,考虑将随机数扩展成2位:
00 p*p
01 p*(1-p)
10 (1-p)*p
11 (1-p)*(1-p)
有上述分析知道,01和10是等概率的,因此我们只需要产生01和10就行了。
于是可以,遇到00和11就丢弃,只记录01和10。可以令,01表示0,10表示1,则等概率1/2产生0和1了。
扩展:
已知一随机发生器,产生0的概率是p,产生1的概率是1-p,现在要你构造一个发生器,使得它构造0和1的概率均为1/2;构造一个发生器,使得它构造1、2、3的概率均为1/3;...,构造一个发生器,使得它构造1、2、3、...n的概率均为1/n,要求复杂度最低。
解答:
对n=2,认为01表示0、10表示1,等概率,其他情况放弃
对n=3,认为001表示1、010表示2,100表示3,等概率,其他情况放弃
对n=4,认为0001表示1、0010表示2,0100表示3,1000表示4,等概率,其他情况放弃
首先是1/2的情况,我们一次性生成两个数值,如果是00或者11丢弃,否则留下,01为1,10为0,他们的概率都是p*(1-p)是相等的,所以等概率了。然后是1/n的情况了,我们以5为例,此时我们取x=2,因为C(2x,x)=C(4,2)=6是比5大的最小的x,此时我们就是一次性生成4位二进制,把1出现个数不是2的都丢弃,这时候剩下六个:0011,0101,0110,1001,1010,1100,取最小的5个,即丢弃1100,那么我们对于前5个分别编号1到5,这时候他们的概率都是p*p*(1-p)*(1-p)相等了。
关键是找那个最小的x,使得C(2x,x)>=n这样能提升查找效率
- 平均要取多少个(0,1)中的随机数才能让和超过1
数学常数最令人着迷的就是,它们常常出现在一些看似与之毫不相干的场合中。 随便取一个 0 到 1 之间的数,再加上另一个 0 到 1 之间的随机数,然后再加上一个 0 到 1 之间的随机数⋯⋯直到和超过 1 为止。一个有趣的问题:平均需要加多少次,才能让和超过 1 呢?答案是 e 次。
#define NUM 9999999 int main() { int sum=0; srand(time(NULL)); for (int i=0;i<NUM;i++) { double val=0; while(val <1) { val+=(rand()/(double)RAND_MAX); sum++; } } printf("%f\n",sum/(double)NUM); return 0; }
为了证明这一点,让我们先来看一个更简单的问题:任取两个 0 到 1 之间的实数,它们的和小于 1 的概率有多大?容易想到,满足 x+y<1 的点 (x, y) 占据了正方形 (0, 1)×(0, 1) 的一半面积,因此这两个实数之和小于 1 的概率就是 1/2 。类似地,三个数之和小于 1 的概率则是 1/6 ,它是平面 x+y+z=1 在单位立方体中截得的一个三棱锥。这个 1/6 可以利用截面与底面的相似比关系,通过简单的积分求得:
可以想到,四个 0 到 1 之间的随机数之和小于 1 的概率就等于四维立方体一角的“体积”,它的“底面”是一个体积为 1/6 的三维体,在第四维上对其进行积分便可得到其“体积”
∫(0..1) (x^3)*1/6 dx = 1/24
依此类推, n 个随机数之和不超过 1 的概率就是 1/n! ,反过来 n 个数之和大于 1 的概率就是 1 - 1/n! ,因此加到第 n 个数才刚好超过 1 的概率就是
(1 - 1/n!) - (1 - 1/(n-1)!) = (n-1)/n!
因此,要想让和超过 1 ,需要累加的期望次数为
∑(n=2..∞) n * (n-1)/n! = ∑(n=1..∞) n/n! = e
- x&(x-1)表达式的意义
求下面函数的返回值(微软) -- 统计1的个数
int func(int x) {int countx = 0;while(x){countx++;x = x&(x-1);}return countx; }
假定x = 9999
10011100001111
答案: 8
思路: 将x转化为2进制,看含有的1的个数。
注: 每执行一次x = x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1将会将该位(x用二进制表示时最右边的一个1)变为0。
判断一个数(x)是否是2的n次方
#include <stdio.h>int func(int x) {if( (x&(x-1)) == 0 )return 1;elsereturn 0; }int main() {int x = 8;printf("%d\n", func(x)); }
注:
(1) 如果一个数是2的n次方,那么这个数用二进制表示时其最高位为1,其余位为0。
(2) == 优先级高于&
本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3878319.html,如需转载请自行联系原作者
一些数据结构的思想(3)相关推荐
- C++两个函数可以相互递归吗_通俗讲:数据结构递归思想
通俗讲:数据结构递归思想 脑容量有限,拒绝花里胡哨 一个递归求阶乘的例子 #如5的阶乘 f(6)=6*5*4*3*2*1 def f(int n) {if n <= 0 : return 1re ...
- 算法与数据结构(面向对象思想)
算法与数据结构和编程之间关系 计算机就是算法与数据结构, 当你选择搜索这类的文章的时候,你已经在翻大山了 编程就是当你翻过一座山的时候,你发现前面还有一座更高的山. LZ从事java工作一年了,最近听 ...
- [数据结构]快速排序
一.问题描述 内部排序是一件具有重大意义的问题,许多项目的实现中都需要用到排序. 我们知道,排序的算法有许多种,每种排序算法的时间复杂度和空间复杂度不尽相同.在解决实际问题时,往往需要根据实际需要选择 ...
- 数据结构整理中。。。
目录 栈 队列 链表 单向链表 双向链表 向链表中插入(写入)数据 单向链表 单向循环链表 双向循环链表 从链表中删除数据 单向(循环)链表 双向循环链表 哈希表 哈希函数 冲突 拉链法 闭散列法 并 ...
- b - 数据结构实验之查找二:平衡二叉树_文件系统的灵魂数据结构 B树
其实平衡二叉树的代码实现已经挺复杂的了,但是一山更比一山高,B树算法的原理和代码实现都比平衡二叉树要更为复杂. 我没有让大家知难而退的意思,面试的时候肯定不会让你写B树这么复杂的算法,大家先听我讲讲B ...
- 数据结构 —— 双向链表(超详细图解 接口函数实现)
系列文章目录 数据结构 -- 顺序表 数据结构 -- 单链表 数据结构 -- 双向链表 数据结构 -- 队列 数据结构 -- 栈 数据结构 -- 堆 数据结构 -- 二叉树 数据结构 -- 八大排序 ...
- 数据结构绪论——什么是数据结构?
为什么写这篇文章 <数据结构>这门课有很多教材,各种概念十分混乱.为了解决概念之间的矛盾,写下这篇博客. 比如严蔚敏的书中存在数据类型和数据结构的混乱,数据类型和ADT的混乱.书上所写本就 ...
- 数据结构课程设计报告(附代码)
数据结构课程设计报告 一.实训目的 通过课程设计,学会运用数据结构知识,针对具体应用,自己设计合理数据结构,确定存储结构,并能设计具体操作算法,选择使用具体语言进行实现.掌握C++较复杂程序的组织和设 ...
- 华科大考研计算机系834大纲之数据结构(三)
栈和队列 本节大纲内容 栈的相关概念与特性 顺序栈的基本操作 链式栈的基本操作 队列的相关概念 顺序队列的基本操作 链式队列的基本操作 栈的应用 补充 循环队列 双端队列 队列的应用 栈的输入输出 本 ...
最新文章
- Pandas中iloc、loc、ix三者的区别
- 通过 Object.prototype.toString.call() 进行类型判断
- android做一个坦克大战小游戏_一个 ECharts 做的猜数小游戏
- 计算机 课题学科代码,学科分类与代码表课题.doc
- jakob slam_Jakob Nielsen针对用户界面设计的第二种可用性启发法
- matlab2010a连接mysql_MATLAB2010a+OpenCV2.3.1+VS2010运行TLD
- 前端学习(2860):简单秒杀系统学习之前端优化
- 麦咭智能机器人宣传片_【头脑风暴】移动机器人能够撬动上亿线下流量,挖掘市场增量吗?...
- TextMate里添加Theme
- 支持全球科研抗疫,艾柏森成功研发Omicron变异株重组蛋白
- Maven clean基本命令
- 云更新网吧系统服务器,云更新网吧无盘
- Springboot 发邮件端口问题
- 安卓pdf阅读器_推荐一款手机PDF阅读器、编辑器xodo docs安卓版
- 四级常见英语短语1000条
- 07 给Form视图添加Chatter(学Odoo,就得Do)
- 深度学习速成版01---神经网络
- 练习4.圆中四只鸭子在同一个半圆的概率——MATLAB
- 了解利用API接口通过网格策略的增长模式
- 页面中的黑白滤镜css3,filter属性
热门文章
- leetcode算法题--子数组按位或操作
- Java synchronized解析
- Safari浏览器的智能跟踪预防工作原理
- adv147(蓝桥杯) 学霸的迷宫 bfs
- 利用ssh+rsync+inotify实现数据的异地实时同步
- monkey测试===ios-monkey测试工具
- vue-cli 自定义指令directive 添加验证滑块
- [PAL编程规范]SAP HANA PAL多项式回归预测分析Polynomial Regression编程规范FORECASTWITHPOLYNOMIALR(预测)...
- JAVA 重载,重写(覆盖)个人理解
- SpringMVC - 非注解的处理器映射器和适配器