网络异常,图片无法展示
|
已有方法 rand7
可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10
生成 1 到 10 范围内的均匀随机整数。
不要使用系统的 Math.random()
方法。
示例 1:
输入: 1 输出: [7] 复制代码
示例 2:
输入: 2 输出: [8,4] 复制代码
示例 3:
输入: 3 输出: [8,1,10] 复制代码
提示:
rand7
已定义。- 传入参数:
n
表示rand10
的调用次数。
进阶:
rand7()
调用次数的 期望值 是多少 ?- 你能否尽量少调用
rand7()
?
解题思路
根据给定的 rand7()
可以获取到 1~7
的均匀随机整数,而本题要获取的是 1~10
的均匀随机整数,想要得到更大的数字,只能相乘或者相加。
所以首先想到的是利用 rand7()*rand7()
获取到 1~49
的均匀随机整数,但是直接相乘后获取到 1~49
并不是均匀的。
那如何才能通过 rand7()
获取到大于 7
的整数呢?
其实可以利用先乘后加的方式,实现如下: 首先让 rand7()-1
就得到了 0~6
的均匀整数,0,1,2,3,4,5,6
然后让它们 *7
就得到了下面的一组数字,0,7,14,21,28,35,42
再利用 rand7()
获取 1~7
的随机均匀整数填补空隙也就是加上 rand7()
, 就得到了 1~49
的随机均匀整数,
舍弃掉 40>
的部分,其余部分 %10 +1
就得到了 1~10
的均匀整数。
动画演示
网络异常,图片无法展示
|
代码实现
var rand10 = function() { let num; while(true){ // 获取 1~49 的均匀随机整数 num = (rand7()-1)*7+rand7(); // 如果小于等于40,则模10+1 返回 if(num<=40) return num%10+1 // 否则舍弃 } }; 复制代码
进阶实现
本题要求我们尽量少调用 rand7()
,在以上实现中,我们把 41~49
的数字舍弃掉了,那为了尽量少的调用 rand7()
,其实就是尽量少的舍弃数字。
所以我们可以利用舍弃的数字,重复上述逻辑,获取更多的值,直到最后舍弃的数字最少。代码如下:
var rand10 = function() { let num; while(true){ // 获取 1~49 的均匀随机整数 num = (rand7()-1)*7+rand7(); // 如果小于等于40,则模10+1 返回 if(num<=40) return num%10+1 // 利用41~49获取 1~63 的均匀随机整数 num = (num-41)*7+rand7() // 如果小于等于60,则模10+1 返回 if(num<=60) return num%10+1 // 利用61~63获取 1~21 的均匀随机整数 num = (num-61)*7+rand7() // 如果小于等于20,则模10+1 返回 if(num<=20) return num%10+1 // 经过以上优化,只会舍弃一个数字 } }; 复制代码
至此我们就完成了 leetcode-470-用 Rand7() 实现 Rand10()
如有任何问题或建议,欢迎留言讨论!