《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;
            }
        }
    }
};

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值