La tarea es claramente encontrar un algoritmo que sea O (1) en la longitud N de la lista de números requerida. Por lo tanto, no importa si necesita el número 100 superior o 10000 números, el tiempo de inserción debe ser O (1).
El truco aquí es que, aunque ese requisito O (1) se menciona para la inserción de la lista, la pregunta no dice nada sobre el orden del tiempo de búsqueda en el espacio de números enteros, pero resulta que esto puede hacerse O (1) también. La solución entonces es la siguiente:
Organice una tabla hash con números para claves y pares de punteros de lista vinculados para valores. Cada par de punteros es el comienzo y el final de una secuencia de lista vinculada. Esto normalmente será solo un elemento y luego el siguiente. Cada elemento en la lista vinculada va al lado del elemento con el siguiente número más alto. Por lo tanto, la lista vinculada contiene la secuencia ordenada de números requeridos. Mantenga un registro del número más bajo.
Tome un nuevo número x de la secuencia aleatoria.
¿Es más alto que el último número más bajo registrado? Sí => Paso 4, No => Paso 2
Golpee la tabla hash con el número que acaba de tomar. ¿Hay una entrada? Sí => Paso 5. No => Tome un nuevo número x-1 y repita este paso (esta es una simple búsqueda lineal descendente, solo tenga paciencia conmigo aquí, esto se puede mejorar y le explicaré cómo)
Con el elemento de lista recién obtenido de la tabla hash, inserte el nuevo número justo después del elemento en la lista vinculada (y actualice el hash)
Tome el número más bajo l registrado (y elimínelo del hash / list).
Golpee la tabla hash con el número que acaba de tomar. ¿Hay una entrada? Sí => Paso 8. No => Tome un nuevo número l + 1 y repita este paso (esta es una simple búsqueda lineal ascendente)
Con un golpe positivo, el número se convierte en el nuevo número más bajo. Ir al paso 2
Para permitir valores duplicados, el hash realmente necesita mantener el inicio y el final de la secuencia de la lista vinculada de elementos que son duplicados. Agregar o eliminar un elemento en una tecla dada aumenta o disminuye el rango al que apunta.
El inserto aquí es O (1). Las búsquedas mencionadas son, supongo, algo así como O (diferencia promedio entre números). La diferencia promedio aumenta con el tamaño del espacio numérico, pero disminuye con la longitud requerida de la lista de números.
Entonces, la estrategia de búsqueda lineal es bastante pobre, si el espacio numérico es grande (por ejemplo, para un tipo int de 4 bytes, 0 a 2 ^ 32-1) y N = 100. Para evitar este problema de rendimiento, puede mantener conjuntos paralelos de tablas hash, donde los números se redondean a magnitudes más altas (por ejemplo, 1s, 10s, 100s, 1000s) para hacer las teclas adecuadas. De esta manera, puede subir y bajar marchas para realizar las búsquedas necesarias más rápidamente. El rendimiento se convierte en un O (rango de números de registro), creo, que es constante, es decir, O (1) también.
Para aclarar esto, imagine que tiene a mano el número 197. Llegaste a la tabla hash de los 10, con '190', se redondea a los diez más cercanos. ¿Cualquier cosa? No. Entonces bajas en 10 segundos hasta que alcanzas decir 120. Luego puedes comenzar en 129 en la tabla hash de 1, luego prueba 128, 127 hasta que alcances algo. Ahora ha encontrado en qué parte de la lista vinculada insertar el número 197. Al ponerlo, también debe actualizar la tabla hash 1 con la entrada 197, la tabla hash 10 con el número 190, 100 con 100, etc. La mayoría de los pasos alguna vez tienes que hacer aquí son 10 veces el registro del rango de números.
Podría haber equivocado algunos de los detalles, pero dado que este es el intercambio de programadores, y el contexto fue entrevistas, espero que lo anterior sea una respuesta lo suficientemente convincente para esa situación.
EDITAR Agregué algunos detalles adicionales aquí para explicar el esquema de tabla hash paralela y cómo significa que las búsquedas lineales pobres que mencioné pueden reemplazarse con una búsqueda O (1). También me di cuenta de que, por supuesto, no hay necesidad de buscar el siguiente número más bajo, porque puede avanzar directamente hacia él al buscar en la tabla hash con el número más bajo y avanzar al siguiente elemento.