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. \(1\sim49\)前10个

  2. \(1\sim49\)前40个,返回 \(t \% 10 + 1\)

  3. 小于等于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();
    }
};
posted @ 2021-09-05 16:08  Ivessas  阅读(60)  评论(0)    收藏  举报