[Leetcode] -470-Rand7()でRand10()を実現

それは基本的に数学の問題全体であり、それを理解するのに長い時間がかかりました。以下は、大物kkbillの高い評価の答えから再現されています。

パート1

rand2()が[1,2]の乱数を均一に生成できると仮定し、[1,4]の乱数を均一に生成したい場合、どのように考慮する必要がありますか?2つのrand2()を追加し、必要なコーナー処理を実行します。次のように:

rand2()+ rand2()=?==> [2,4]
   1 + 1 = 2
   1 + 2 = 3
   2 + 1 = 3
   2 + 2 = 4

//乱数生成の範囲を[1、n]に減らすには、前のステップの結果の後に1を引きます
(rand2()-1)+ rand2()=?==> [1,3]
   0 + 1 = 1
   0 + 2 = 2
   1 + 1 = 2
   1 + 2 = 3

この方法で処理された結果の最も致命的なポイントは、生成された結果が等しい確率ではないことであることがわかります。この簡単な例では、2を生成する確率は50%ですが、1と3を生成する確率は25%です。したがって、単に加算プロセスに依存すると、結果の確率が等しくなりません。他の方法を検討する必要があります。(rand2()-1)の部分に2を掛けてみましょう。変更された部分は次のとおりです。

(rand2()-1)×2 + rand2()=?==> [1,3]
   0 + 1 = 1
   0 + 2 = 2
   2 + 1 = 3
   2 + 2 = 4

 奇跡的なことが起こり、奇妙な知識が増えました。このような処理により、得られる結果は正確に[1,4]の範囲になり、各数値は等しい確率で取得されます。したがって、このメソッドを使用すると、rand4()をrand2()で実装できます。さらにいくつかの例を試した後、それが普遍的であることがわかり、結論に達しました。

(rand_X()-1)×Y + rand_Y()==> [1、X * Y]の範囲の乱数は、等しい確率で生成でき、rand_XY()を実現します。

パート2

では、rand2()からrand4()を実装することについてどう思いますか?これは非常に簡単です。rand4()は、余りを取り、それに1を加えることにより、[1,4]の乱数を均一に生成することが知られています。以下に示すように、結果も同じ確率です。

rand4()%2 + 1 =?
   1%2 + 1 = 2
   2%2 + 1 = 1
   3%2 + 1 = 2
   4%2 + 1 = 1

 パート3

では、この質問に戻りましょう。rand7()を知っているので、rand10()からrand7()を実装する必要があります。前の分析では、rand10()を実装するには、最初にrand_N()を実装し、Nが10より大きく、10の倍数であることを確認する必要がありますこのように、[1,10]の範囲の乱数は、rand_N()%10 +1を介して取得できます。rand_N()を実装するには、次のように、パート1で説明したメソッドによってrand7()を変換できます。

(rand7()-1) × 7 + rand7()  ==> rand49()

しかし、この方法で実現されたNは10の倍数ではありません!これにどう対処するか?これにはサンプリングの拒否の知識が含まれます。つまり、サンプリング結果が必要な範囲内にない場合、それは破棄されます。上記の分析に基づいて、以下のコードを振り返ると、理解しやすいはずです。

class Solution extends SolBase {
    public int rand10() {
        while(true) {
            int num = (rand7() - 1) * 7 + rand7(); // 等概率生成[1,49]范围的随机数
            if(num <= 40) return num % 10 + 1; // 拒绝采样,并返回[1,10]范围的随机数
        }
    }
}

 

 

おすすめ

転載: blog.csdn.net/qq_39328436/article/details/114657595