LC470-用 Rand7() 实现 Rand10()
470. 用 Rand7() 实现 Rand10()
关键在于证明“等概率”
① rand10 \(\rightarrow\) rand7
基本想法是当随机到\(1\sim7\)的数时返回,否则舍弃,继续随机(拒绝采样)。下面证明返回的\(1\sim7\)都是等概率的。
对于\(1\sim7\)的任意一个数,则返回的概率为:
\[\begin{align}
&\frac{1}{10} + \frac{3}{10}*\frac{1}{10} + (\frac{3}{10})^2 * \frac{1}{10}+...+(\frac{3}{10})^{(n - 1)} * \frac{1}{10}\\
=&\frac{1}{10} * (1 + \frac{3}{10} + (\frac{3}{10})^2 + ... + (\frac{3}{10})^{(n - 1)}),n \rightarrow \infty \\
=&\frac{1}{10} * \frac{1 - (\frac{3}{10})^{(n)}}{\frac{7}{10}}\\
=&\frac{1}{10} * \frac{10}{7}\\
=&\frac{1}{7}
\end{align}
\]
② rand7 \(\rightarrow\) rand10
\(rand7()\)一次一定不够,必定需要rand7两次,而且需要将\(1\sim7\)映射到更多大的范围,然后拒绝采样大范围中概率相同的某些数。
这里采用映射 \((rand7()- 1 )* 7 + rand7()\) (类似二维矩阵,对于两个维度的选择是独立事件,相乘概率相同,范围\(1\sim49\))
-
取\(1\sim49\)前10个
-
取\(1\sim49\)前40个,返回 \(t \% 10 + 1\)
-
小于等于40 返回 \(t \% 10 + 1\)
大于40 ,将多出部分重新映射: \((x - 40 - 1)* 7 + rand7()\)
小于等于60,返回 \(t \% 10 + 1\)
大于60,将多出部分重新映射: \((x - 60 - 1)* 7 + rand7()\)
小于等于20,返回 \(t \% 10 + 1\)
大于20,舍弃(多出部分继续映射无法超过10个数)
// The rand7() API is already defined for you.
// int rand7();
// @return a random integer in the range 1 to 7
//2版本代码
class Solution {
public:
int rand10() {
int t = (rand7() - 1) * 7 + rand7();
if(t > 40)return rand10();
return t % 10 + 1;
}
};
// The rand7() API is already defined for you.
// int rand7();
// @return a random integer in the range 1 to 7
//版本3写法
class Solution {
public:
int rand10() {
int t = (rand7() - 1) * 7 + rand7();
if(t <= 40)return t % 10 + 1;
t = (t - 40 - 1) * 7 + rand7();
if(t <= 60)return t % 10 + 1;
t = (t - 60 - 1) * 7 + rand7();
if(t <= 20)return t % 10 + 1;
return rand10();
}
};