题目描述

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

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

思考

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

题解

刚看到这题觉得挺有意思的,再看一脸懵逼,这怎么做?后来看了题解才懂了,原来是这个意思。

题目要求只能给你用 rand7 函数,也就是均匀生成 1 到 7 之间的整数。但是现在要求你生成 1 到 10 之间的整数,那么肯定只生成一次是不够的,因为状态数都不够嘛,那就生成多次看看。

如果生成两次,那么就得到了两个 1 到 7 之间的整数,然后怎么转换为 1 到 10 呢。如果这两个数两两组合,那么可以得到 49 种状态,可以用来表示 1 到 49 这 49 个数字,如果想要让 1 到 10 均匀分布,那么每个数字最多只能分配 4 次。具体分配情况如下所示:

        1  2  3  4  5  6  7
8  9  10 1  2  3  4
5  6  7  8  9  10 1
2  3  4  5  6  7  8
9  10 1  2  3  4  5
6  7  8  9  10 .  .
.  .  .  .  .  .  .

注意:每行下标代表第一个随机数 1 到 7 (r1 表示),每列下标代表第二个随机数 1 到 7 (r2 表示)。而转换后的随机数可以表示为 ,注意到最后 9 个数没有用到,因为它们不足以表示 1 到 10 这 10 个数,如果表示了概率就不等了。

那么如果根据上面式子算出来落在了最后 9 个数范围内怎么办呢?这时候我们就拒绝它,重新生成两个数就行了,直到落在前 40 个数范围里。这种方法的期望采样次数是多少呢?

所以平均只需要 2.45 次就可以均匀的采样到 1 到 10 之间的整数啦。那么这背后的数学原理是什么呢?其实就是拒绝采样

蒙特卡洛方法大家应该都很熟悉了,就是采样来求分布,比如求一个直径为 1 的圆的概率,我们可以用一个边长为 1 的正方形包住它,然后随机往里面扔豆子,扔 10000 个,看最后有多少落在了圆里面,那么除以 10000 就是圆的面积了。

而拒绝采样跟这类似,就是一个分布 形式比较复杂,累积分布函数不好求,所以不好采样。那么我们可以用一个标准分布 来近似它,并且用系数 来控制 的大小,使得 ,这就类似于上面的用正方形包住了圆形嘛。 然后 是好采样的嘛,所以根据 采样出一个 ,然后再在 0 到 之间采样一个数 ,如果 落在了 0 到 之间,那就接受这个采样,否则就拒绝它,重新采样。这种方法采出来的 是服从分布 的,因为你采样得到 的概率是 ,而接受的概率是 ,所以最终接受 的概率就是 。因此 要设置的尽量小,这样接受的概率才大,期望的采样次数才少。但是又不能设置太小,因为要满足 的前提条件才行。

代码

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 r1, r2, num;do {r1 = rand7();r2 = rand7();num = (r1 - 1) * 7 + r2;} while (num > 40);return (num - 1) % 10 + 1;}
};

后记

这题题目虽简单,背后的思想还是很有意思的,拒绝采样可以用在深度学习中的很多应用场景里,特别是你的分布很难进行采样的时候,就可以用拒绝采样来模拟。

当然这题还有其他采样方法可以缩小期望采样次数,比如如何利用这 9 个被拒绝的点呢?留给大家思考(其实是我懒得写了)。

每日算法系列【LeetCode 470】用 Rand7() 实现 Rand10()相关推荐

  1. LeetCode 470. 用 Rand7() 实现 Rand10()(随机概率)

    1. 题目 已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数. 不要使用系统的 Math.random() 方法. ...

  2. leetcode 470. 用 Rand7() 实现 Rand10()

    难度:中等 频次:55 题目: 给定方法 rand7 可生成 [1,7] 范围内的均匀随机整数,试写一个方法 rand10 生成 [1,10] 范围内的均匀随机整数. 你只能调用 rand7() 且不 ...

  3. 重复次数最多的 子串_每日算法系列【LeetCode 424】替换后的最长重复字符

    题目描述 给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次.在执行上述操作后,找到包含重复字母的最长子串的长度. 示例1 输入: s = &quo ...

  4. 求栈中元素个数算法_每日算法系列【LeetCode 315】计算右侧小于当前元素的个数...

    题目描述 给定一个整数数组 nums ,按要求返回一个新数组 counts .数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量. 示例 ...

  5. 数组最大可以开多大_每日算法系列【LeetCode 689】三个无重叠子数组的最大和

    题目描述 给定数组 由正整数组成,找到三个互不重叠的子数组的最大和. 每个子数组的长度为 ,我们要使这 个项的和最大化. 返回每个区间起始索引的列表(索引从 0 开始).如果有多个结果,返回字典序最小 ...

  6. 如何表示数组所有数都不等于一个数_每日算法系列【LeetCode 523】连续的子数组和...

    题目描述 给定一个包含非负数的数组和一个目标整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数. 示例1 输入: [ ...

  7. 如何表示数组所有数都不等于一个数_每日算法系列【LeetCode 330】按要求补齐数组...

    题目描述 给定一个已排序的正整数数组 nums ,和一个正整数 n .从 [1, n] 区间内选取任意个数字补充到 nums 中,使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的 ...

  8. 序列复杂度怎么看_每日算法系列【LeetCode 376】摆动序列

    题目描述 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5] 是一个 ...

  9. 找出最具竞争力的子序列_每日算法系列【LeetCode 376】摆动序列

    题目描述 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5] 是一个 ...

  10. 【LeetCode笔记】470. 用Rand7()实现Rand10()(Java、概率)

    文章目录 题目描述 代码 & 思路 更新版 三刷 - 极简版 题目描述 貌似是比较高频的面试题目啊,有学概率论内味了(讲道理我概率论学得不好) 代码 & 思路 先用Rand7实现Ran ...

最新文章

  1. android各种权限及说明
  2. MySQL group replication
  3. 架空输电线路运行规程_[精品课程]金具的种类架空输电线路设计
  4. P8207-[THUPC2022 初赛]最小公倍树【Kruskal】
  5. Python os.walk() 方法--输出在目录中的文件名
  6. JS中配置打开邮箱的链接
  7. Linux进程间通信——使用命名管道
  8. SPSS编程-统计自动化-VBA脚本开发
  9. UIFont 字体设置
  10. oracle函数创建及调用
  11. Linux From Scratch docker lfs build 在Fedora 31 Linux上自己动手从源码一步一步编译出一个x86_64架构LFS Linux操作系统
  12. OSPF沉默接口配置
  13. windows2003 php 加速,window_Win 2003 加速****,微软的Windown Server 2003尽管它是 - phpStudy...
  14. AV1代码学习:encoder_encode函数
  15. Surface Pro 6 黑苹果 CLOVER 配置文件,全球首发(转载)
  16. 基于JavaSwing开发天猫购物商城系统(用户 管理员角色) 课程设计 毕业设计源码
  17. 万兆交换机用什么网线_万兆交换机SFP+端口是否能与千兆交换机SFP端口连接?...
  18. HTML + CSS + JS做一个绘画分享网站[开源项目]
  19. 从0开始学c语言-总结01-c语言的粗略认识和快捷键
  20. camtasia studio2022汉化屏幕录屏录像

热门文章

  1. CentOS下配置多个Tomcat同时运行 本篇文章来源于 Linux公社网站(www.linuxidc.com)
  2. 213. Orchard学习 二 3、001.IOrchardHost 与Autofac
  3. 最全最新个税计算公式---今天你税了吗?
  4. JAVA大数——lightoj1024
  5. python爬虫之路——对斗破苍穹进行关键字提取,制作噪声云图
  6. 前端开发的工具,库和资源总结
  7. django multidb --- router
  8. Git使用- 基本命令
  9. [科普]关于文件头的那些事
  10. 【RN6752】模拟高清AHD芯片或成为车机新标配