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

最近做了一些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;
}
生成结果如下:

关于面试中经常出现的根据一个随机数构造另外的随机数的解法_第1张图片

算法的关键就是两次运用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。

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

你可能感兴趣的:(关于面试中经常出现的根据一个随机数构造另外的随机数的解法)