1. 解法
1.描述:
- 先用`(rand7()-1)*7+rand7()`来构造rand49,
- 舍去[41-49]的case,剩下rand40
- rand10 = rand40%10 + 1
2.代码描述
// java
public int rand10() {
int rand40 = 40;
while (rand40 >= 40) {
rand40 = (rand7() - 1) * 7 + rand7() - 1;
}
return rand40 % 10 + 1;
}
2.解法分析(本文重点)
2.1 如何构造rand49
首先看两个反例
反例1: rand[2-14] = rand7() * 2
rand7() * 2构造出来的是rand[2,4,6,8,10,12,14],而不是rand[2-14],因为3,5,7,9,11,13,这几个case都不会出现
反例2:rand[2-14] = rand7() + rand7()
这里就不能像反例1中来解释了,这里必须用概率论来解释。首先左边rand[2-14]表示[2,3,4,5,6,7,8,9,10,11,12,13,14]这些数字出现的概率是相等的,都是1/13。但是rand7() + rand7()组成的case中却不是。
用Pi表示左边rand[2-14]元素i的概率,用pi表示rand7中每一个元素i的概率。比如
- P2 = p1*p1,
- P3=p1*p2 + p2*p1 = 2/49, 所以很显然P2!=P3。同理可以继续计算
- P4=p1*p3 + p2*p2 + p3*p1 = 3/49,所以 P2!=P3!=P4。
所以rand[2-14] != rand7() + rand7()
那么 rand49 = (rand7()-1)*7+rand7() 成立吗?成立的。这里不做证明,简单描述一下, (rand7()-1)*7 是把rand7放大7倍,也就是变成了 [0,7,14,21,28,35,42],再用rand7()来填补0-7、7-14、14-21、21-28、28-35、35-42之间的空缺,所以P1=P2=P3=...=P49的
2.2 为什么就能舍去[41-49]的case
一句话,因为P1=P2=P3=...P47=P48=P49 = 1/49。舍去其中的任意个case,剩下的一样也是概率相等的——概率不在是1/49。
2.3 rand10 = rand40%10 + 1
%10可以,/4就不行吗?其实都是可以的,都是在1-40的case中映射出10个case,而且都是这种映射是不会造成结果概率不等的。
直接舍去[10-49]可以吗?可以的,功能可以实现,但是性能大打折扣,折扣为原来的1/4。因为%10时,可用case是40个;而舍去[10-49]则可用case为10个。(第2次编辑加)
2.4 举一反三
我们不但能构造出rand10,也能构造出很多小于49的random(random2、random3、...、random49)。
3.总结
1.强行让自己回忆了一下概率论和多rand的认知。
2.leetcode题目链接 和 解法的出处 (该贴还有进阶版解法2)