Leetcode470。Rand7()を使用してRand10()を実装します(サンプリングを拒否します)

2021年3月19日金曜日、天気は良いです[過去を嘆いたり、現在を無駄にしたり、未来を恐れたりしないでください]


1.はじめに

470. Rand7()を使用してRand10()を実装する
ここに画像の説明を挿入

2.問題解決(棄却サンプリング)

(randX()-1)* Y + randY()は、[1、X * Y]の範囲の乱数を等しい確率で生成できます。

詳細については、以下を参照してください。最も基本的な観点から乱数を均等に生成する方法

2.1方法1

class Solution {
    
    
public:
    int rand10() {
    
    
        while(true){
    
    
            int a = rand7();
            int b = rand7();
            int num = (a-1)*7 + b; // rand 49
            if(num <= 40) return num % 10 + 1; // 拒绝采样
            
            a = num - 40; // rand 9
            b = rand7();
            num = (a-1)*7 + b; // rand 63
            if(num <= 60) return num % 10 + 1;
            
            a = num - 60; // rand 3
            b = rand7();
            num = (a-1)*7 + b; // rand 21
            if(num <= 20) return num % 10 + 1;
        }
    }
};

予想される計算:

A = 2 + 9/49 * (1 + 3/63 * 1) = 2.192419825072886
p = 9/49 * 3/63 * 1/21 = 0.00041649312786339027
EX = A + A * p + A * p^2 + ... = A / (1 - p) = 2.1933333333333334

2.2方法2

class Solution {
    
    
public:
    int rand10() {
    
    
        while(true){
    
    
            int a = rand7(), b = rand7();
            while(a == 7) a = rand7();   //让a只能为1到6,保证奇数偶数个数相同
            while(b > 5) b = rand7();    //让b只能为1到5
            return (a & 1 ? 0 : 5) + b;  //相当于将10分解为两个部分,1/2 * 1/5 = 1/10
        }
    }
};

予想される計算:

E1 = 2 (int a = rand7(), b = rand7();)
E2 = 1/7 * 1 + 1/7 * 1/7 * 1 + 1/7 * 1/7 * 1/7 * 1... =  1/6 (while(a == 7) a = rand7();)
E2 = 2/7 * 1 + 2/7 * 2/7 * 1 + 2/7 * 2/7 * 2/7 * 1... =  2/5 (while(b > 5) b = rand7();)
E = E1 + E2 + E3 = 2 + 1/6 + 2/5 = 2.566666666666667

参照

https://leetcode-cn.com/problems/implement-rand10-using-rand7/solution/yong-rand7-shi-xian-rand10-by-leetcode/

https://leetcode-cn.com/problems/implement-rand10-using-rand7/solution/cong-zui-ji-chu-de-jiang-qi-ru-he-zuo-dao-jun-yun-/

おすすめ

転載: blog.csdn.net/m0_37433111/article/details/115006393