前一段时间看了看大公司的笔试题,其中有一道关于随机概率的问题,感觉挺好玩的,仔细想了想又不太会搞所以看了一些答案,其中有一种感觉挺好,我就拿出来说说,并且随机概率这类题我也扩展了,和大家分享分享。写的不好或者有问题还请指教改正。
最初的题目:
现在已知有一个函数Rand5(),该函数输出1到5随机一个数,这五个数都是等概率的,现在要求用这个函数写一个Rand10()函数,函数要求输出1到10中随机一个数,并且是等概率的。
如果你没见过,请自己先想一想怎么做?如果你看过了,那么请你往下看扩展。
怎么样,有解决方法吗?没有的话请看参考答案,有的话对比一下,看看哪个更好,希望不吝赐教。
已经有了Rand5()函数,那么我们就有1到5的数可以等概率的出现,因此我们可以在一个循环里面调用Rand5,让其只输出1和2两个数,当然循环几次能输出1和2,我们这里不用去考虑,因为不管几次输出,最后结果只能是1和2其中之一,因此这个循环输出数1和2的概率都为1/2,单独调用rand5()能输出1到5的5个数的概率都为1/5,那么1到10的10个数我们可以这样构造。
do{
m = Rand5();
}while(m>2)
n = Rand5();
num = n + 5*(m -1);
其中num的范围为1到10,概率为1/2 * 1/5 = 1/10,满足题目要求。
演变的题目:
已知Rand5(),求Rand7(),要求同样是等概率。
这到题其实跟上面的一样,不过不要想着直接拼出概率为1/7的方法,我自认为我做不到,那么直接不行我们可以间接制造。
当然所谓的间接是指要借助另一个函数,这个函数就是Rand10(),还记得上面制造1和2的数吗,概率为1/2,那么我们可以借助Rand10()求出1到7中的任何一个数,当然概率为1/7,解释和上面的一样。这里有人可能问了Rand10()得出的数还有概率,这里我这样认为,我不管Rand10()的概率,我只知道这个函数只输出1到10中的一个数,那么我利用它输出Rand7(),这个函数就只能输出1到7中的一个,而且上面我们已经得到Rand10()是等概率的,所以这7个数也是等概率的,就和Rand5()制造1和2一样。
do{
m = Rand10();
}while(m>7)
num = m;
其中num的范围为1到7,概率为1/7,满足题目要求。
扩展:
已知Randn1(),求Randn2(),要求同上面的。
这里我们可以先判断n1和n2的大小
1、当 n1>n2的时,直接利用循环调用Randn1(),直到输出小于等于n2的数。
2、当n2 = 2*n1时,先求1和2的数,再利用 num = n + 5*(m -1);求出所求范围。
3、当2*n1 > n2 > n1时,先求出Rand2*n1(),在利用Rand2*n1()求出Randn2()。
4、当n2 > 2*n1时,先求出Randn*n1(),其中n=3,4 。。。n。在利用Randn*n1()求出Randn2()。
以上是我想的方法,如有错误或不同意见,欢迎评论指正。