[Leetcode] -470-Realice Rand10 () con Rand7 ()

Es básicamente un problema matemático completo y tomó mucho tiempo entenderlo. Lo siguiente es una reproducción de la respuesta de gran elogio del gran kkbill.

Parte 1

Suponiendo que rand2 () puede generar números aleatorios de [1,2] uniformemente, y ahora quiero generar números aleatorios de [1,4] uniformemente, ¿cómo deberíamos considerarlo? Agregue dos rand2 () y realice el procesamiento de esquina necesario. como sigue:

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

// Para reducir el rango de generación de números aleatorios a [1, n], reste 1 después del resultado del paso anterior
(rand2 () - 1) + rand2 () =? ==> [1,3]
   0 + 1 = 1
   0 + 2 = 2
   1 + 1 = 2
   1 + 2 = 3

Se puede observar que el punto más fatal de los resultados procesados ​​por este método es que los resultados generados no son de igual probabilidad . En este ejemplo simple, la probabilidad de producir 2 es del 50%, mientras que la probabilidad de producir 1 y 3 es del 25%. Por lo tanto, simplemente confiar en el proceso de adición hará que el resultado sea una probabilidad no igual. Necesitamos considerar otros métodos. Intentemos multiplicar la parte de (rand2 () - 1) por 2. La parte modificada es la siguiente:

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

 Sucedieron cosas milagrosas, aumentaron los conocimientos extraños. Mediante dicho procesamiento, el resultado obtenido es exactamente el rango de [1,4], y cada número se toma con igual probabilidad. Por lo tanto, usando este método, rand4 () puede ser implementado por rand2 (). Después de probar algunos ejemplos más, descubrí que es universal y llegué a la conclusión:

(rand_X () - 1) × Y + rand_Y () ==> Se pueden generar números aleatorios en el rango de [1, X * Y] con la misma probabilidad, lo que realiza rand_XY ()

Parte 2

Entonces, ¿qué piensas de implementar rand2 () a través de rand4 ()? Esto es muy simple, se sabe que rand4 () generará uniformemente números aleatorios de [1,4], tomando el resto y agregándole 1. Como se muestra a continuación, el resultado también es la misma probabilidad.

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

 Parte 3

Ok, ahora volvamos a esta pregunta. Conociendo rand7 (), es necesario implementar rand10 () a rand7 (). Con el análisis anterior, para implementar rand10 (), primero debe implementar rand_N () y asegurarse de que N sea mayor que 10 y sea un múltiplo de 10 . De esta manera, se pueden obtener números aleatorios en el rango de [1,10] mediante rand_N ()% 10 + 1. Para implementar rand_N (), podemos transformar rand7 () mediante el método descrito en la parte 1, de la siguiente manera:

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

¡Pero la N realizada de esta manera no es un múltiplo de 10! Como lidiar con esto? Esto implica el conocimiento del " rechazo de muestreo ", es decir, si un resultado de muestreo no está dentro del rango requerido, se descarta. Según el análisis anterior, mirando hacia atrás en el código a continuación, debe ser fácil de entender.

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]范围的随机数
        }
    }
}

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_39328436/article/details/114657595
Recomendado
Clasificación