《LeetCode之每日一题》:139.用 Rand7() 实现 Rand10()

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:139.用 Rand7() 实现 Rand10()相关的知识,希望对你有一定的参考价值。

implement-rand10-using-rand7


题目链接: 用 Rand7() 实现 Rand10()

有关题目

已有方法 rand7 可生成 17 范围内的均匀随机整数,
试写一个方法 rand10 生成 110 范围内的均匀随机整数。

不要使用系统的 Math.random() 方法。
示例 1:

输入: 1
输出: [7]
示例 2:

输入: 2
输出: [8,4]
示例 3:

输入: 3
输出: [8,1,10]
提示:

rand7 已定义。
传入参数: n 表示 rand10 的调用次数。
进阶:

rand7()调用次数的 期望值 是多少 ?
你能否尽量少调用 rand7() ?

题解

法一:拒绝采样
参考官方题解

思路:
在拒绝采样中,如果生成的随机数满足要求,
那么就返回该随机数,否则会不断生成,
直到生成一个满足要求的随机数为止。

Tips
Tip1

(randX() - 1)*Y + randY() 可以等概率的生成
[1, X * Y]范围的随机数
证明:
randX()的范围[1, X]randX()-1的范围为[0, X-1](randX() - 1) * Y的范围是[0, (X-1)*Y](非连续整数集),
(randX() - 1) * Y + randY()的范围自然就是[1, X * Y](连续整数集)

Tip2

①idx为什么不是 col*row

官方题解刚开始给出示例,乘的话,生成的数就不是等概率了,故不使用

②而是 idx = col + (row - 1) * 7

而加的话就可以使其等概率的生成数字,由于col = rand7()等概率生成1~7数字,每个数字出现的概率皆为1 / 7,

,row = rand7()同理,又idx = col + (row - 1) * 7中row减去一个常数,再整体乘一个常数,仍不改变其整体等概率性质
// 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 row, col, idx;
        do{
            row = rand7();
            col = rand7();
            idx = col + (row - 1) * 7;
        }while(idx > 40);
        return 1 + (idx - 1) % 10;
        //return 1 + idx % 10;
    }
};


法二:优化拒绝采样

思路:
我们重复利用法一中的拒绝的数据,即[41, 49],通过取余我们可以得到[1, 9]之间的随机数,
此时调用一次rand7()我们可以得到,[1, 63]之间的等概率出现的数字,同理我们拒绝[61, 63]之间的数字,取余,可以得到[1, 3]之间的数字

此时再调用一次rand7(),我们可以得到[1, 21]之间等概率出现的数字,取余,得到[1],

此时调用rand7()得到 [1, 7]之间数字,不满足题意,故我们不采用调用本次rand7(),我们回到调用两次rand7()生成[1, 49]之间的数字

// 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 row, col, idx;
        while(true){
            row = rand7();
            col = rand7();
            //range[1, 49]
            idx = row + (col - 1) * 7;
            if (idx <= 40){
                return 1 + (idx - 1) % 10;
            }
            row = idx - 40;
            col = rand7();
            //range[1, 63]
            idx = col + (row - 1) * 7;
            if (idx <= 60){
                return 1 + (idx - 1) % 10;
            }
            row = idx - 60;
            col = rand7();
            //range[1, 21]
            idx = col + (row - 1) * 7;
            if (idx <= 20){
                return 1 + (idx - 1) % 10;
            }
        }
    }
};

以上是关于《LeetCode之每日一题》:139.用 Rand7() 实现 Rand10()的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 139. 单词拆分

《LeetCode之每日一题》:200.

《LeetCode之每日一题》:228.截断句子

《LeetCode之每日一题》:155.回文链表

《LeetCode之每日一题》:150.二进制求和

《LeetCode之每日一题》:63.有效的括号