关于面试中经常出现的根据一个随机数构造另外的随机数的解法

来源:互联网 发布:c语言程序停止运行 编辑:程序博客网 时间:2024/06/05 10:56

最近做了一些Tencent及几家公司的面试题,发现有一种关于产生随机数的类型的题目。看到多有大牛们做出来,而且效率很高,也有不知道怎么做的,最近根据几个产生随机数的题目整理一下,发现所有的类似题目可以用一种万能钥匙解决。故分享,欢迎发表不同看法,欢迎吐槽。

题目一:给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数。

利用随机函数rand()函数生成一个等概率随机生成整数1到5的函数Rand5(),然后根据Rand5()生成Rand7(),代码如下:

#include <iostream>using namespace std;int Rand5(){int n =1 + rand()%5;return n;}int Rand7(){int n ,tmp1 ,tmp2;do {tmp1 = Rand5();    tmp2 = Rand5();n = (tmp1-1)*5+tmp2;//n是可以取1~25的随机的数。} while (n>21);//当n>21舍去,这样n只能取1~21,对7取模就能取1~7之间的随机数return 1+n%7;}int main(){for (int i = 0 ; i < 100 ; i++){cout<<Rand5()<<" ";}cout<<endl;for (int j = 0 ; j < 100 ; j++){cout<<Rand7()<<" ";}cout<<endl;return 0;}
生成结果如下:



算法的关键就是两次运用Rand5(); tmp1 = Rand5();tmp2 = Rand5();n = (tmp1-1)*5+tmp2;n的最大值为25,为了满足产生的1到7等概率,所以n最大应该取7的倍数,所以当n>21时应舍去,为了测试是否概率真的相等,写一个测试函数:

int main(){const int Max = 10000000;int a[7] = {0};for (int ii = 0 ; ii < Max ; ++ii){switch (Rand7()){case 1:a[0]++;break;case 2:a[1]++;break;case 3:a[2]++;break;case 4:a[3]++;break;case 5:a[4]++;break;case 6:a[5]++;break;case 7:a[6]++;break;default:cerr<<"Error!"<<endl;exit(-1);}}for (int r = 0 ; r<7 ; r++){cout<< r+1<<":"<<setw(6)<<setiosflags(ios::fixed)<<setprecision(2)<<double(a[r])/Max*100<<"%"<<endl;}return 0;}

题目二:已知rand7() 可以产生 1~7 的7个数(均匀概率),利用rand7()  产生rand10()   1~10(均匀概率)

解法与上面类似,同样只用两个rand7()生成rand10()即可。各位可以自己试试。
另外,看见一个大牛的方法,似乎比以上更为简单,现贴出代码,供各位欣赏:

int rand10(){int temp1;int temp2;do{temp1 = rand7();}while(temp1>5);do{temp2 = rand7();}while(temp2>2);return temp1+5*(temp2-1);}

temp1只取1到5,temp2只取1到2,即可等概率取到1到10。

个人觉得两种方法有异曲同工之妙,所以大多数利用一个等概率随机数构造另外一个等概率随机数,只需两次使用概率函数即可。