思路:
1、用Rand10()实现Rand7()比较容易(大数实现小数):
第一次就命中的p:7/10
第二次命中的p:3/10+7/10
第三次命中的p:+
以此类推:根据等比数列公式得出:

2、用Rand7()实现Rand10()(小数实现大数):
将小数映射为大数,并且要求在区间[x,y]内得数都能等概率获得
(RandX()-1)*X+RandY()可以等概率获得区间[1,X*Y]内的数
3、现在只有Rand7(),则第一步:(Rand7()-1)*7+Rand7()得到[1,49]内的某个数
如果是[41,49]间的数,再次进行大数映射:(num-40-1)*7+Rand7()可以得到[1,63]间的某个数
如果是[61,63]间的数,再次进行大数映射:(num-60-1)*7+Rand7()可以得到[1,21]间的某个数
如果是21则直接舍弃,这样就只需要舍弃一个数
代码:
class Solution extends SolBase {
public int rand10() {
while(true){
//映射到大数[1,49]
int num = (rand7()-1)*7+rand7();
if(num<=40){
//预防出现10、20、30、40的情况
return num%10+1;
} else {
//从41~49中选,重新映射到大数[1,63]
num = (num-40-1)*7+rand7();
if(num<=60){
return num%10+1;
} else {
//从61~63中选,重新映射到大数[1,21],只需要舍弃一个数
num = (num-60-1)*7+rand7();
if(num<=20){
return num%10+1;
}
//否则舍弃21,重新进入循环,这样时间会显著减少
}
}
}
}
}
分解:
1、在[1,49]情况下,如果是[1,40],可以通过与10取模+1,来获取10以内的数
+1是防止出现整数10、20、30、40的情况
该博客详细介绍了如何利用Rand7()生成器有效地实现Rand10()。通过多次映射和概率计算,确保了在[1,10]区间内所有数字等概率出现。具体步骤包括将[1,49]映射到大数,处理[41,49]和[61,63]的特殊情况,以及在适当的时候舍弃超出范围的数值。代码示例展示了整个过程,实现了高效且公平的Rand10()随机数生成。

617

被折叠的 条评论
为什么被折叠?



