已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。
不要使用系统的 Math.random() 方法。
示例 1:
输入: 1
输出: [7]
示例 2:
输入: 2
输出: [8,4]
示例 3:
输入: 3
输出: [8,1,10]
提示:
rand7 已定义。
传入参数: n 表示 rand10 的调用次数。
进阶:
rand7()调用次数的 期望值 是多少 ?
你能否尽量少调用 rand7() ?
思路分析
首先,rand7()是[1,7]等概率,我们需要实现[1,10]等概率,因此需要扩展rand7().
第一个方法:x = rand7() + rand7() -1 范围在[1,13],若x > 10则重新循环,这样可以扩展范围,但不是等概率的。
比如 1 只能是1+1-1,而 2 可以是1+2-1和2+1-1.
我们可以考虑乘法实现。
首先,x = rand7(),x在[1,7]等概率,那么x-1在[0,6]等概率,(x-1)*7在[0,7,14,21,28,35,42]这7个离散的数等概率。
这时,(x-1)*7 + rand7()就在[1,49]等概率了。
我们可以利用的范围在[1,40],通过对10取模得到[1,10]的等概率。 x = 1+x%10
若x > 40,剩余的数字将x -= 40会在[1,9],如果直接舍弃,利用率就比较低,因此我们对这 9 个数字再进行一次乘法扩展。
x = (x-1)*7 + rand7(),和上面一样,先是[0,8],乘以 7 后到[0, 7, 14... 56]的等概率离散数字,加上rand7()就是[1,63]等概率数字。
我们可以利用[1,60]对10取模得到等概率,对于x > 60的数据,将x -= 60可以用[1,2,3],接下来再进行一次乘法扩展。
x = (x-1)*7 + rand7(),得到[1,21]等概率数字,用到[1,20],剩下的 1 舍弃即可。
// The rand7() API is already defined for you.
// int rand7();
// @return a random integer in the range 1 to 7
class Solution {
public:
int rand10() {
int x;
while(1)
{
x = (rand7()-1)*7 + rand7(); //[1,49], 1~40利用 41到49回收
if(x <= 40) return 1+x%10;
x -= 40;
//下面是[1,9], 乘法扩展
x = (x-1)*7 + rand7(); //[1,63]等概率
if(x <= 60) return 1+x%10;
//下面是[1,3], 乘法扩展
x -= 60;
x = (x-1)*7 + rand7(); //[1,21]
if(x <= 20) return 1+x%10;
}
return x;
}
};

该博客探讨如何通过已有的rand7方法生成1到10之间的均匀随机整数,不使用Math.random()。文章详细介绍了利用乘法和取模运算扩展rand7的范围,通过多次调用rand7并处理溢出情况,最终实现rand10。这种方法涉及到随机数生成的策略和概率论知识。
371

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



