题目描述
解题思路
题目的关键是,怎么把 rand7 产生的 1,2,3,4,5,6,7 映射到 1,2,3,4,5,6,7,8,9,10
我们先来看看怎么从 rand10 映射到 rand7
如果映射到了就是 1,2,3,4,5,6,7,直接返回就可以了
如果是 8,9,10 呢?
重新映射就可以了,此处的关键在于证明是否为等概率事件,
当结果在 1 - 7 之间,每个数字的概率是
(7 / 10) * (1 / 7) = 1 / 10
对于 8 - 10:
第一次没命中,第二次命中
(3 / 10) * (1 / 10)
因此我们的代码可以这么写
function rand7() {
let num = rand10()
while (true) {
if (num <= 7) return num
num = rand10()
}
}
说了这么多,其实是想说,要注意怎么生成等概率事件的数字
关键公式
(rand7() - 1) * 7 + rand7()
第一项范围:[0, 7, 14, 21, 28, 35, 42],
第二项范围:[1, 7]
加起来是 49, 此处的关键在于,证明等概率事件
证明等概率事件
设第一项取值为 a,第二项为 b,来看和的范围
a = 0, [1, 7]
a = 7,[8, 14]
...
再多写一些可以看到,其实左右取不同值的时候,刚好能覆盖所有数字
此处衍生一个公式,可以自己看看 (randX() - 1) * Y + randY() => [1, (x- 1)y + y
本题的范围怎么搞出来
可以通过拿到 [0, 40] 之后,取末尾数字再加 1 就得到了(1 + tail % 10)
or
拿到最后 9 个数字,再加一
反正只要是等概率就可以!
代码
/**
* The rand7() API is already defined for you.
* var rand7 = function() {}
* @return {number} a random integer in the range 1 to 7
*/
var rand10 = function () {
let num = (rand7() - 1) * 7 + rand7()
while (true) {
if (num >= 40) return (num % 10) + 1
num = (rand7() - 1) * 7 + rand7()
}
}