¿Cómo podemos generar un número aleatorio con igual probabilidad en el rango [1 … n] st, no pertenece al conjunto inválido de números S = {xi | 1 <= xi <= n e i [matemáticas] \ en [/ matemáticas] [1… k] yk <n} utilizando la memoria O (k); siempre que podamos llamar a la función aleatoria solo una vez?

Hay una solución que solo necesita tiempo [matemático] O (\ log k) [/ matemático] para generar un número aleatorio. Obviamente, solo tiene sentido usarlo si vas a generar muchos números aleatorios. Si desea hacerlo solo una vez, es mejor usar la solución más simple de Raziman TV: de todos modos, necesita tiempo [matemático] \ Omega (k) [/ matemático] para cualquier inicialización.

Como en la solución de Raziman TV, el número aleatorio que generaremos en nuestro algoritmo será un valor aleatorio distribuido uniformemente entre 1 y [math] nk [/ math], inclusive. Y también el valor devuelto será el mismo: el [math] (nk) [/ math] -th número válido más pequeño. Simplemente lo calcularemos de una manera más eficiente.

Usaremos la memoria [math] O (k) [/ math] para almacenar los números prohibidos [math] k [/ math] en orden ordenado . La clave es darse cuenta de que:

  • los valores prohibidos [math] k [/ math] dividen los valores válidos en segmentos contiguos [math] k + 1 [/ math] (algunos de ellos posiblemente vacíos),
  • podemos usar la búsqueda binaria para encontrar el segmento correcto,
  • y dentro del segmento correcto podemos encontrar el valor correcto en tiempo constante.

Ejemplo: suponga que el séptimo valor prohibido más pequeño es 47. Esto significa que entre {1, …, 47} hay 40 valores válidos y 7 valores prohibidos. Si el valor aleatorio interno es 40 o menos, queremos generar un número menor que 47, y si es mayor que 40, la salida será mayor que 47.

Bonificación adicional: en lugar de una matriz ordenada, almacene los valores prohibidos en un árbol binario equilibrado. Entonces también puede agregar nuevos valores prohibidos rápidamente. Uno de los posibles usos: generar [matemática] k [/ matemática] valores aleatorios distintos de {1, …, n} en [matemática] O (k \ log k) [/ matemática] tiempo.

Suponiendo que tiene una función rand (i) que genera un número aleatorio en [1 … i] con probabilidad uniforme, aquí hay una solución que tiene O (K) complejidad de tiempo y espacio.

Almacene el conjunto inválido de números en una matriz ordenada S [1 … K]. Necesitamos elegir un número entero uniformemente entre los números enteros NK restantes. Para esto, genere un entero aleatorio x en el rango [1 … NK] usando rand (NK). Ahora, si podemos encontrar el número x no elegido en [1 … N], podemos resolver el problema.

Podemos usar la matriz S para encontrar este número. Si el primer elemento de S es mayor que x, x es el número x no elegido. De lo contrario, incremente x en 1 y observe la segunda posición en S. Continúe con esto hasta que la siguiente posición en S contenga un número mayor que x (o hemos llegado al final de la matriz). Como hemos incrementado x en el número de posiciones sobre las que hemos saltado, hemos encontrado el número x no elegido como se esperaba.

  x = rand (NK)

 para pos = 1 a K:
   si x 

Dado que hay números NK no elegidos y cada uno de ellos se elige con la misma probabilidad, cada número válido se elige de manera uniforme al azar. Obviamente, este método usa solo memoria O (K). La complejidad del tiempo es O (K) también.

PD : Esta respuesta se copia esencialmente de otra de mis respuestas .

More Interesting

Entonces, ¿es una estructura de datos un algoritmo que describe cómo organizar las cosas?

Cómo memorizar los algoritmos del cubo de Rubik

¿Cómo calculamos la complejidad espacio-temporal de un algoritmo?

¿Qué es el algoritmo de sincronización YAWNS?

Cómo identificar la recursividad en un problema de programación

¿Cómo no es aplicable el algoritmo de Dijkstra a los gráficos con pesos negativos? ¿No podemos simplemente agregar alguna constante a cada peso para que cada peso sea positivo, y luego aplicar el algoritmo de Dijkstra para encontrar el camino más corto?

¿Cuáles son las aplicaciones de las tablas hash?

¿Podría alguien ayudarme con el problema del algoritmo 'Intervalo casi ordenado'?

Cómo escribir un algoritmo de diccionario en un programa en C

¿Cuál es la mejor manera de aprender el algoritmo KMP para poder recordarlo fácilmente?

Cómo escribir un algoritmo que diseña guiones

Estructuras de datos: ¿Cuál es una explicación intuitiva de los árboles rojo-negros?

En C, el nombre de la matriz denota la dirección del elemento cero de la matriz. ¿Es esto solo una regla, o tiene alguna razón asociada?

¿Cómo debo usar el libro Introducción a los algoritmos de Cormen de manera efectiva? ¿Es mejor elegir un tema que haya encontrado en algún lugar de la programación competitiva y leer un algoritmo relacionado con eso o revisarlo de principio a fin?

¿Cuáles son los algoritmos de vanguardia para las características de textura eficientes para la recuperación de imágenes?