1. 面试过程中,遇到这么一道题,给定一个随机生成器,生成0和1的概率分别为0.5,那么如何构造一个生成0和1的概率分别是0.3和0.7的随机生成器?
考虑随机生成器fun()生成0和1的概率都为0.5,那么我们可知,生成1或者0为等概率事件,而要使得生成0和1概率变为0.3和0.7,那么可以考虑将其生成的数字0,1进行组合,例如:0000,0001,0010,0011,0100...1111,要达到题目所要求的概率,可以在组合数为0000~0010时输出0,组合数为0011~1010时输出1,当组合数为其他时丢弃,这样我们便可以生成题目要求的随机生成器。参考:http://blog.youkuaiyun.com/martin_liang/article/details/8811641
int fun2()
{
int n=0;
int n1=fun();
int n2=fun();
int n3=fun();
int n4=fun();
n|=n1;
n|=n2<<1;
n|=n3<<2;
n|=n4<<3;
if(n<=2)
return 0;
else if(n<10)
return 1;
else
return fun2();
}
2. 如果随机生成器生成0和1的概率分别为p和1-p,那么如何构造生成0和1为等概率的随机生成器?
我们还是采用如上题所用思路,考虑生成0,1进行组合,那么生成00概率为p^2,生成01概率为p(1-p),生成10概率为(1-p)p,生成11概率为(1-p)^2,我们可以发现生成01和生成10概率是一样的,因此可以考虑使用这个作为生成0,1的等概率随机生成器。
int fun2()
{
int n=0;
int n1=fun();
int n2=fun();
n|=n1;
n|=n2<<1;
if(n==1)
return 0;
else if(n==2)
return 1;
else
return fun2();
}
数学表示就是 C(2x,x) >=n ,我们只需要知道x就能够知道序列要多长了。而且中间必定有超过n个概率为{p(1-p)}^x不相等序列。问题就可以解决了。参考:http://blog.163.com/kevinlee_2010/blog/static/16982082020120792429856/
4. 已知函数rand7()等概率返回1到7随机自然数,如何利用这个rand7()构造rand10() 随机产生0~9的数。
rand7()产生的范围只是随机的生成0~6,这显然不能满足rand10()的要求,可以考虑将rand7()进行扩展,那么这些生成的数就都是等概率生成的,但是要考虑扩展后要对应到0~9的区间,我们可以采用下面程序中val=v1*7+v2的构造方法,这是为了随机产生两个0~6之间的数,然后组合成一个7进制的数,这个数的范围大于0~9的区间,并且产生的两个数之间相互独立,概率相等,因此可以被用来对rand7()进行扩展。
int rand10()
{
int v1=rand7();
int v2=rand7();
int val=v1*7+v2;//可以将v1*7+v2看做是两位的7进制数,数值范围在0~49之间
if(t<4)
return 0;
else if(t<8)
return 1;
else if(t<12)
return 2;
else if(t<16)
return 3;
else if(t<20)
return 4;
else if(t<24)
return 5;
else if(t<28)
return 6;
else if(t<32)
return 7;
else if(t<36)
return 8;
else if(t<40)
return 9;
else
return rand10();
}