最近做了一些Tencent及几家公司的面试题,发现有一种关于产生随机数的类型的题目。
看到多有大牛们做出来,而且效率很高,也有不知道怎么做的,最近根据几个产生随机数的题目整理一下,发现所有的类似题目可以用一种万能钥匙解决。
故分享,欢迎发表不同看法,欢迎吐槽。
题目一:给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数。
利用随机函数rand()函数生成一个等概率随机生成整数1到5的函数Rand5(),然后根据Rand5()生成Rand7(),代码如下:
[cpp]view plaincopy
1.#include <iostream>
ing namespace std;
3.int Rand5()
4.{
5.int n =1 + rand()%5;
6.return n;
7.}
8.int Rand7()
9.{
10.int n ,tmp1 ,tmp2;
11.do
12. {
13. tmp1 = Rand5();
14. tmp2 = Rand5();
15. n = (tmp1-1)*5+tmp2;//n是可以取1~25的随机的数。
16. } while (n>21);//当n>21舍去,这样n只能取1~21,对7取模就能取1~7之间的随机
数
17.
18.return 1+n%7;
19. }
20.int main()
21.{
22.for (int i = 0 ; i < 100 ; i++)
23. {
24. cout<<Rand5()<<" ";
25. }
26. cout<<endl;
27.for (int j = 0 ; j < 100 ; j++)
28. {
29. cout<<Rand7()<<" ";
30. }
31. cout<<endl;
32.return 0;
33.}
生成结果如下:
算法的关键就是两次运用
Rand5(); tmp1 = Rand5();tmp2 = Rand5();n = (tmp1-1)*5+tmp2;n的最大值为25,为了满足产生的1到7等概率,所以n最大应该取7的倍数,所以当n>21时应舍去,为了测试是否概率真的相等,写一个测试函数:
[cpp]view plaincopy
1.int main()
2.{
3.const int Max = 10000000;
4.int a[7] = {0};
5.for (int ii = 0 ; ii < Max ; ++ii)
6. {
7.switch (Rand7())
8. {
9.case 1:a[0]++;break;
10.case 2:a[1]++;break;
11.case 3:a[2]++;break;
12.case 4:a[3]++;break;
13.case 5:a[4]++;break;
14.case 6:a[5]++;break;
15.case 7:a[6]++;break;
16.default:cerr<<"Error!"<<endl;exit(-1);
17. }
18. }
19.for (int r = 0 ; r<7 ; r++)
20. {
21. cout<< r+1<<":"<<setw(6)<<setiosflags(ios::fixed)<<setprecision(2)<<
double(a[r])/Max*100<<"%"<<endl;
22. }
23.return 0;
24.}
题目二:已知rand7() 可以产生 1~7 的7个数(均匀概率),利用rand7() 产生rand10() 1~10(均匀概率)
解法与上面类似,同样只用两个rand7()生成rand10()即可。
各位可以自己试试。
另外,看见一个大牛的方法,似乎比以上更为简单,现贴出代码,供各位欣赏:[cpp]view plaincopy
1.int rand10()
2.{
3.int temp1;
4.int temp2;
5.do
6. {
7. temp1 = rand7();
8. }while(temp1>5);
9.do
10. {
11. temp2 = rand7();
12. }while(temp2>2);
13.return temp1+5*(temp2-1);
14.}
temp1只取1到5,temp2只取1到2,即可等概率取到1到10。
个人觉得两种方法有异曲同工之妙,所以大多数利用一个等概率随机数构造另外一个等概率随机数,只需两次使用概率函数即可。