精选力扣500题 第34题 LeetCode 470. 用 Rand7() 实现 Rand10()【c++ / java 详细题解】

1、题目

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

不要使用系统的 Math.random()方法。

示例 1:

输入: 1
输出: [7]

示例 2:

输入: 2
输出: [8,4]

示例 3:

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

提示:

  1. rand7已定义。
  2. 传入参数: n 表示 rand10的调用次数。

进阶:

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

2、思路

定理

rand_n()能等概率生成1n的随机整数,则有(rand_n() - 1) * n + rand_n()能等概率生成1n * n的随机整数。

举例

(rand7()-1) * 7 + rand7(): 相加元素无重复, 即等概率构成了 1~49, 即rand49()

注: 即在0,7,14,21,28,35,42 基础上等概率加1, 2, 3, 4, 5, 6, 7

即:

第一个rand70时,再加上第二个rand7()可以生成:1, 2, 3, 4, 5, 6, 7 (均为 1 / 7 1/7 1/7概率)

第一个rand71时,再加上第二个rand7()可以生成:8, 9, 10, 11, 12, 13, 14

以此类推

第一个rand77时,再加上第二个rand7()可以生成:43, 44, 45, 46, 47, 48, 49 (均为 1 / 7 1/7 1/7概率)

我们只需要[1,10] 范围内的整数,但是会生成[1,49] 范围内的整数,相当于有 4 / 5 4/5 4/5的数字都是无用的,需要重新生成。因此,我们需要尽可能多的充分利用[1,49] 范围内的数字。

方法是选择 [1, 40] 范围里的数,通过取余运算来得到 [1, 10] 范围的数,这里我们为了简化代码将[1,40]的数字都减1,取成[0,39]

数字xx%10余数
0, 10, 20 , 300
1,11,21,311
2,12,22,322
9,19, 29,399

余数09出现的概率都是相等的,最后再加1取到[1,10]

3、c++代码

// 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 t = (rand7() - 1) * 7 + rand7();  // 取到1~49之间的数字
        if (t > 40) return rand10(); //如果数字大于40,再次进行rand7()运算
        return (t - 1) % 10 + 1; //0~9余数加一取到1~10
    }
};

4、java代码

/**
 * 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() {
        int t = (rand7() - 1) * 7 + rand7();  // 取到1~49之间的数字
        if (t > 40) return rand10(); //如果数字大于40,再次进行rand7()运算
        return (t - 1) % 10 + 1; //0~9余数加一取到1~10
    }
}

原题链接:470. 用 Rand7() 实现 Rand10()


最近一直在刷力扣题,计划是刷完500道力扣高频面试题,有想一起组队刷题的或者在刷题上有困惑的小伙伴可以加我微信或者QQ,免费答疑。备注算法学习即可。

微信:z13663570205

QQ:1622840727

如果我的文章对你有帮助的话,还请点个赞鸭!!!
在这里插入图片描述

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林小鹿@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值