LeetCode 470. 用 Rand7() 实现 Rand10()
一道经典面试题。
题目描述
已有方法 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() ?
解题思路
这道题的关键思路是拒绝采样。对于范围在 [0,7)
的整型随机数,我们可以用i、j两个数组合成一个 7进制数 ij,也就是 10进制里的 i*7+j
,这个数将随机均匀分布在 [0,49)
的范围内。
此时我们可以从中选出一定量的数字,使得这写数字可以恰好平均分成10份,把这10份分别映射到数字 0~9 即可。对于多出来的数字,直接拒绝,重新随机生成。
最典型的,选取 [0,40)
按照模10的余数进行分组,对于40及以上的数字,拒绝并重新生成。
参考代码
/*
* @lc app=leetcode.cn id=470 lang=cpp
*
* [470] 用 Rand7() 实现 Rand10()
*/
// @lc code=start
// 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() {
for (;;) {
int i = rand7() - 1;
int j = rand7() - 1;
int res = i * 7 + j;
if (res >= 40) continue;
return res % 10 + 1;
}
return -1;
} // AC
};
// @lc code=end