已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。
不要使用系统的 Math.random() 方法。
示例 1:
输入: 1
输出: [7]
示例 2:
输入: 2
输出: [8,4]
提示:
rand7 已定义。
传入参数: n 表示 rand10 的调用次数。
解题思路
这个问题有两个形式:
- rand 大数生成小数
- rand 小数生成大数
第一种
譬如 rand10得到rand7:思路很简单,如果得到8-10,就继续调用重新采样,直到处于1-7为止。但是遇到 rand50得到rand7 呢?做个取余就好1-49 映射到 1-7很容易,50就继续循环调用
第二种
调用一次rand7只能得到7种结果,那如果调用两次呢?可以得到7*7=49种组合结果,生成 [1, 49] 之间的随机整数,我们只用到其中的 40 个,用来实现 Rand10(),而拒绝剩下的 9 个数
# The rand7() API is already defined for you.
# def rand7():
# @return a random integer in the range 1 to 7
class Solution(object):
def rand10(self):
"""
:rtype: int
"""
idx = (rand7() - 1) * 7 + rand7()
while idx>40:
idx = (rand7() - 1) * 7 + rand7()
return (idx - 1) % 10 + 1
# return idx % 10 + 1
优化
上一种方法中要舍弃[41,49],舍弃的有点多,可以想办法少丢弃一点。当产生的数在[41,49]时,利用 idx = (idx - 40 - 1) * 7 + rand7()=[1, 63],这样我们可以得到1-63之间的随机数,只要舍弃3个即可,那对于这三个舍弃的,还可以再来一轮,idx = (idx - 60 - 1) * 7 + rand7()=[1, 21],这样我们可以得到1-21之间的随机数,只要舍弃一个即可。
# The rand7() API is already defined for you.
# def rand7():
# @return a random integer in the range 1 to 7
class Solution(object):
def rand10(self):
"""
:rtype: int
"""
while True:
idx = (rand7() - 1) * 7 + rand7()
if idx<=40:
return idx%10 + 1
idx = (idx - 40 - 1) * 7 + rand7()
if idx<=60:
return idx%10 + 1
idx = (idx - 60 - 1) * 7 + rand7()
if idx<=20:
return idx%10 + 1