470. 用 Rand7() 实现 Rand10()

578 阅读2分钟

题描述

思路:

  • 如果能用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;
            }
        }
    }
}