随机概率相关的面试题

转至:http://blog.csdn.net/luckyxiaoqiang/article/details/8788906

1. 已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10。
只调用一次rand7()肯定无法达到目的。我们调用两次rand7(),这样我们可以随机的得到1~49中的一个数,为什么呢?
我们将49分成7段,1~7,8~14,15~21,22~28,29~35,36~42,43~49,第一次rand7()随机选择其中一段,第二次rand7(),随机选择段内的一个数,这样我们得到的1~49中的数都是等概率的。
然后我们想办法将1~49映射到1~10,显然无法直接映射,我们只取1~40,对于41~49我们抛弃,这样并没有影响其随机特性,因为1~40中的每一个数都是等概率出现的。
然后(1~4)→1,(5~8)→2,……。这样就完成了rand10的功能。

[cpp]  view plain copy
  1. int rand10()  
  2. {  
  3.     int x;  
  4.     do  
  5.     {  
  6.         x = (rand7()-1)*7+rand7();  
  7.     }while(x > 40)  
  8.     return (x-1)%4+1;  
  9. }  
2. 有一个随机生成器randA(),以p的概率返回0,1-p的概率返回1,利用这个randA()构造randB(),使randB()等概率的返回0和1,即0.5的概率返回0,0.5的概率返回1。
只调用一次randA(),我们也无法实现randB(),所以也要调用两次。
调用两次共有4种结果,得到00,概率为p*p;得到01,概率为p*(1-p);得到10,概率为(1-p)*p;得到11,概率为(1-p)*(1-p)。
容易发现有两种情形概率相等,01和10,那么我们可以把这两种情况映射为返回0或1,如果得到的是其它两种情况,那么我们就继续再调用两次randA();
[cpp]  view plain copy
  1. int randB()  
  2. {  
  3.     int x1, x2;  
  4.     do  
  5.     {  
  6.         x1 = randA();  
  7.         x2 = randA();  
  8.     }while(x1+x2 != 1)  
  9.     return x1;  
  10. }  
3. 程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。从概率的角度来说,我们希望得到没有重复的选择,其中每个选择出现的概率相等。
[cpp]  view plain copy
  1. void generate(int m,int n)  
  2. {  
  3.     int t = m;  
  4.     for(int i = 0; i < n; i++)  
  5.         if(Rand(0,n-1-i) < t) //即以t/(n-i)的概率执行下面的语句  
  6.         {  
  7.             printf("%d\n",i);  
  8.             t--;  
  9.         }  
  10. }  

其中,Rand(a,b)随机产生[a,b]范围内的一个整数。
上述算法源自Knuth的《计算机程序设计艺术 第2卷 半数值算法》。Knuth 给出了概率上的证明,每个数选中的概率都是m/n,而且恰好选中m个数。

简单验证一下:

第0个数,被选中的概率是

第1个数,被选中的概率是

第2个数,被选中的概率是

4. 给出一个n个元素的数组,对所有元素随机中排,也就是说,n!种可能的元素排列中随机选出一种。
[cpp]  view plain copy
  1. void random_shuffle(int A[], int n)  
  2. {  
  3.     for(int i = n-1; i > 0; i--)  
  4.     {  
  5.         swap(a[i], a[Rand(0, i)]);//即随机选择0~i中的一个元素  
  6.     }  
  7. }  
其中, Rand(a,b)随机产生[a,b]范围内的一个整数。
简单验证一下,详细证明请参考 Knuth的《计算机程序设计艺术 第2卷 半数值算法》。
当对于第n-1个位置,swap
(a[n-1], a[Rand(0, n-1)]),使得每一个元素出现在位置n-1的概率都是1/n
再考虑第n-2个位置,每个元素出现在第n-2个位置上的概率是(n-1)/n * 1/(n-1) = 1/n,即在第n-1个位置没有被选中,然后在第n-2个位置被选中;
再考虑第n-3个位置,每个元素出现在第n-3个位置上的概率是(n-1)/n * (n-2)/(n-1) * 1/(n-2) = 1/n,在第n-1和第n-2个位置都没有被选中,然后在第n-3个位置被选中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值