Dado un número N y un flujo continuo de enteros de entrada, ¿podría encontrar dos números en el flujo cuya suma fuera el primer número N?

El problema no requiere encontrar los primeros dos números, sino cualquier par de enteros viables de la secuencia.

El entrevistador se habría sorprendido y complacido de tener una respuesta casi perfecta.

Él o ella estaba buscando su interpretación y el marco del problema. Estaban buscando su descubrimiento de lo que era desconocido o indefinido en el problema, eso sería importante. Estaban buscando para ver si hiciste preguntas para tratar de responder esas incógnitas, o si tenías una solución lista incluso con los puntos sin respuesta. Si los puntos permanecieron desconocidos, ¿asumió una opción, declarando esa limitación de la solución, o ramificó el problema, reconociendo que se necesitaban soluciones en cada alternativa?

Para principiantes:

No conocemos la distribución de los valores dentro del flujo interminable de enteros, ni si la distribución cambia con el tiempo.

Tampoco sabemos si el programa controla la entrada del siguiente número, o si la llegada de la secuencia es impulsada por un proceso externo.

No nos dieron un límite de tiempo.

Ni siquiera nos dijeron si los enteros estaban limitados por los valores representables más grandes en el lenguaje de la solución programada, o si estaríamos tomando enteros, en el sentido matemático puro, como en el conjunto de todos los números enteros.

Y no es cierto que un hash nunca agote la memoria.

Un posible enfoque:

Suposiciones

  1. Los números se pueden leer de la secuencia en orden, cuando nuestro programa está listo para leerlos.
  2. Los números están delimitados +/- algún múltiplo de N.
  3. Todos los números dentro de ese rango finalmente están en la secuencia.
  4. Como el flujo de números es continuo, cada número entero volverá a aparecer, dado el tiempo suficiente.

Si el entrevistador acepta que estos supuestos están permitidos, escriba un programa a

lee el número inicial N

Si N = cero

Imprimir 1 y – 1

Más

Imprime 0 y el número N

salida.

El escenario excluye el almacenamiento de toda la secuencia, por lo que no puede simplemente seguir recorriendo el conjunto para encontrar la solución. (respuesta estándar) Tenemos que ser creativos y aplicar la lógica de otros dominios …

Para cualquier número N, hay un número fijo de combinaciones aditivas y permutaciones. La propiedad comunicativa de la suma nos permite centrarnos en las permutaciones únicas. Por lo tanto, en realidad solo estamos buscando un pequeño subconjunto de pares de números menores que N. (ver imagen a continuación)

La solución más simple y rápida que se me ocurre sería calcular estas permutaciones aditivas y luego evaluar / procesar la transmisión de datos en vivo.

Pseudocódigo aproximado: encuentra 10 en la secuencia:

  1. Calcule las permutaciones aditivas donde N = 10 … ((N-1) / 2) redondeado hacia arriba = 5
  2. Cree una matriz de 4 dimensiones para almacenar los pares de números y un marcador de posición para su índice / ubicación en la secuencia.
  3. Cargue pares de números en la matriz de almacenamiento. Comenzaría en N – 1 y luego iteraría hacia atrás en el conjunto para cada permutación aditiva. (9 + 1, 8 + 2, 7 + 3, 6 + 4, 5 + 5)
  4. Procesando el flujo de datos … Descarte cualquier valor que sea mayor que N. (si es posible)
  5. Almacene el primer valor de índice de N … Las iteraciones futuras no deberían sobrescribir este valor.
  6. Verifique si el elemento de matriz actual tiene ambos índices rellenados:
  1. SI no, vuelva al paso 4
  2. En caso afirmativo, vaya al siguiente paso
  • Imprima el elemento de matriz actual que representa la primera permutación aditiva de N.
  • Existe un método probabilístico estándar para resolver problemas como este utilizando filtros Bloom. Pero debe estar satisfecho con una respuesta que probablemente sea correcta.

    Calcula cuánta memoria estás dispuesto a usar y crea un filtro Bloom de ese tamaño. Luego, a medida que ingrese cada número X en la secuencia, determine si el filtro Bloom contiene X. Si lo tiene, envíe X y N – X. Si no lo tiene, agregue N – X al filtro Bloom.

    Pro: funciona en números de entrada de tamaño ilimitado.

    Pro: si hay una respuesta “temprana” en la secuencia, se garantizará que el filtro la encuentre.

    Con: el filtro Bloom se llena y eventualmente se te garantizará un falso positivo.

    Supongamos que tenemos una memoria [math] m [/ math] -bit y hemos procesado elementos de flujo [math] n [/ math] hasta ahora. Entonces, la probabilidad de un solo falso positivo, si usamos hashes [math] k [/ math], es aproximadamente [math] (1-e ^ {- kn / m}) ^ k [/ math].

    Digamos que usamos 8 GiB de memoria para el filtro Bloom, o [math] m = 2 ^ {41} [/ math] bits, y queremos manejar un flujo de al menos 8 mil millones de números con una tasa de error de menos del 1% .

    Si seleccionamos [matemática] k = 8 [/ matemática], la tasa de error en cualquier búsqueda individual es menor que [matemática] 4.6 * 10 ^ {- 13} [/ matemática]. Más de 8 mil millones de números, eso significa que la probabilidad de que no obtengamos falsos positivos es mayor que [matemáticas] (1-4.6 * 10 ^ {- 13}) ^ {8 * 10 ^ 9} \ aproximadamente 0.996 [/ matemáticas], o aproximadamente 0.4% de probabilidad de que el algoritmo devuelva un resultado incorrecto en ese punto.

    ¿Obtener el número actual en la secuencia menos N y encontrar ese número?