470. Implement Rand10() Using Rand7() #
题目 #
Given a function rand7
which generates a uniform random integer in the range 1 to 7, write a function rand10
which generates a uniform random integer in the range 1 to 10.
Do NOT use system’s Math.random()
.
Example 1:
Input: 1
Output: [7]
Example 2:
Input: 2
Output: [8,4]
Example 3:
Input: 3
Output: [8,1,10]
Note:
rand7
is predefined.- Each testcase has one argument:
n
, the number of times thatrand10
is called.
Follow up:
- What is the
expected value for the number of calls to
rand7()
function? - Could you minimize the number of calls to
rand7()
?
题目大意 #
已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。不要使用系统的 Math.random() 方法。
提示:
- rand7 已定义。
- 传入参数: n 表示 rand10 的调用次数。
进阶:
- rand7()调用次数的 期望值 是多少 ?
- 你能否尽量少调用 rand7() ?
解题思路 #
- 给出
rand7()
要求实现rand10()
。 rand7()
等概率地产生1,2,3,4,5,6,7。要想得到rand10()
即等概率的生成 1-10 。解题思路是先构造一个randN()
,这个 N 必须是 10 的整数倍,然后 randN % 10 就可以得到rand10()
了。所以可以从rand7()
先构造出rand49()
,再把rand49()
中大于等于 40 的都过滤掉,这样就得到了rand40()
,在对 10 取余即可。- 具体构造步骤,
rand7() --> rand49() --> rand40() --> rand10()
:rand7()
等概率地产生 1,2,3,4,5,6,7.rand7() - 1
等概率地产生 [0,6].(rand7() - 1) *7
等概率地产生 0, 7, 14, 21, 28, 35, 42(rand7() - 1) * 7 + (rand7() - 1)
等概率地产生 [0, 48] 这 49 个数字- 如果步骤 4 的结果大于等于 40,那么就重复步骤 4,直到产生的数小于 40
- 把步骤 5 的结果 mod 10 再加 1, 就会等概率的随机生成 [1, 10]
- 这道题可以推广到生成任意数的随机数问题。用
randN()
实现randM()
,M>N
。步骤如下:- 用
randN()
先实现randX()
,其中 X ≥ M,X 是 M 的整数倍。如这题中的 49 > 10; - 再用
randX()
生成randM()
,如这题中的 49 —> 40 —> 10。
- 用
- 举个例子,用
rand3()
生成rand11()
,可以先生成rand27()
,然后变成以 22 为界限,因为 22 是 11 的倍数。生成rand27()
的方式:3 * 3 * (rand3() - 1) + 3 * (rand3() - 1) + (rand3() - 1)
,最后生成了rand11()
;用rand7()
生成rand9()
,可以先生成rand49()
,然后变成以 45 为界限,因为 45 是 9 的倍数。生成rand49()
的方式:(rand7() - 1) * 7 + (rand7() - 1)
,最后生成了rand9()
;用rand6()
生成rand13()
,可以先生成rand36()
,然后变成以 26 为界限,因为 26 是 13 的倍数。生成rand36()
的方式:(rand6() - 1) * 6 + (rand6() - 1)
,最后生成了rand13()
;
代码 #
package leetcode
import "math/rand"
func rand10() int {
rand10 := 10
for rand10 >= 10 {
rand10 = (rand7() - 1) + rand7()
}
return rand10%10 + 1
}
func rand7() int {
return rand.Intn(7)
}
func rand101() int {
rand40 := 40
for rand40 >= 40 {
rand40 = (rand7()-1)*7 + rand7() - 1
}
return rand40%10 + 1
}