leetcode刷题笔记——470.rand7()实现rand10()

题目:

在这里插入图片描述

思路:

要求rand10()输出均匀分布并不代表着每个输出的数概率为1/10。

运行两次rand7(),第一次作为十位第二次作为个位,比如第一次取得6,第二次取得3,则(63)为一次组合,这个组合为7进制数。

将此数转化为十进制数,公式为7*(6-1)+3=38。即运行两次rand7()可以得到的十进制数应该为7*(rand7()-1)+rand7()。

我们令res=7*(rand7()-1)+rand7(),显然res∈[1,49]。因为两次运行rand7()独立,所以res取得[1,49]内的每个数的概率都是1/49。实际上到这里这题已经解答出来了。

入门解:

令res=7*(rand7()-1)+rand7(),只要res大于10,拒绝采样,重新取res直到res取值小于等于10。

// 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 res=11;
        while(res>10){ 
           res = (rand7()-1)*7 + rand7();
        }
        return res;
    }
};

进阶解:

上述代码在res大于10时就要重新运行两次rand7(),也就是我们抛弃了11-49的数,这使得时间效率低下。实际上res在取得[1,40]时都是等概率,只需要取余即可:

// 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 res=41;
        while(res>40){ 
           res = (rand7()-1)*7 + rand7();
        }
        return res%10+1;
    }
};

注意对10取余的结果范围为[1,9],需要+1,不影响分布
此时我们丢弃了41-49,此算法还可以再优化,即取得41-49时,它们也是等概率的。可以再令9*(rand7()-1)+(res_41_to_49 - 40),此式的取值范围为[1,63],按照之前的理论可以抛弃3个数,此数已经足够小了不需要再往下了。

抛弃9个数的运行结果如下:
在这里插入图片描述
结果还行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值