题描述
思路:
- 如果能用rand7 生成 rand49就好了,这样就可以直接rand49除去后9位(为了均匀)再 % 10.
- 如何用rand7生成rand49?
-
rand7 * rand7不行,生成的数不能能cover1~49,而且每个数字出现的概率可能不相等. -
找规律发现,用
(rand7 - 1)* 7 + rand7可以cover 1~49,并且每个数字出现的概率均为1 / 49.
-
代码一:
生成的数字分布为: 1 ~ 10
11 ~ 20
21 ~ 30
31 ~ 40
41 ~ 49,所以这一组必须被舍弃
class Solution extends SolBase {
public int rand10() {
while (true) {
int m = rand7();
int n = rand7();
int rand = (m - 1) * 7 + n;
// int rand = (m - 1) * n + n;//一开始写成这样了
if (rand <= 40) {
return rand % 10 + 1;
}
}
}
}
代码二:
在方法一中,我们生成 [1, 49] 的随机数,若生成的随机数 x 在 [41, 49] 中,我们则拒绝 x。然而在 x 被拒绝的情况下,我们得到了一个 [1, 9] 的随机数,如果再调用一次 Rand7(),那么就可以生成 [1, 63] 的随机数。我们保留 [1, 60] 并拒绝 [61, 63]:这是 [1, 3] 的随机数。我们继续调用 Rand7(),生成 [1, 21] 的随机数,保留 [1, 20] 并拒绝 [1]。此时 [1] 已经没有任何用处,若出现了拒绝 1 的情况,我们就重新开始生成 [1, 49] 的随机数。
注意细节
- 每次都要新生成一个rand7()
- return1~10的数字时的写法,rand要-1
/**
* The rand7() API is already defined in the parent class SolBase.
* public int rand7();
* @return a random integer in the range 1 to 7
*/
class Solution extends SolBase {
public int rand10() {
while (true) {
int m = rand7();
int n = rand7();
int p = (m - 1) * 7 + n;
if (p <= 40) {
return p % 10 + 1;
}
int rand9 = p % 10;// 此时p为41-49随机
int rand7 = rand7();
p = (rand7 - 1) * 9 + rand9;
if (p <= 60) {
return p % 10 + 1;
}
int rand3 = p % 10;// 此时p为61-63随机
rand7 = rand7();
p = (rand7 - 1) * 3 + rand3;
if (p <= 20) {
return p % 10 + 1;
}
}
}
}