← Datos y decisiones ETAPA 02 · 30 MIN

Buscar con un invariante

Usa el orden para descartar respuestas imposibles sin perder la correcta.

Abrir en el laboratorio ↗

AL TERMINAR, PODRÁS

  • Explicar por qué la búsqueda binaria exige una entrada ordenada
  • Mantener un intervalo de búsqueda semiabierto
  • Manejar a propósito los valores ausentes y los duplicados
La búsqueda binaria cumple una promesa: si el objetivo existe, está en el intervalo semiabierto [lo, hi), que incluye lo y excluye hi.

Descripción del diagrama: 3, 8, 12, 19, 27, 31, 44, 50; el objetivo 19 aún puede estar aquí: 0–3; 0: lo; 2: mid: 12 < 19; 4: hi (excluido)

El orden da información

Una búsqueda lineal revisa elementos hasta encontrar una coincidencia o llegar al final.

La búsqueda binaria (binary search) aprovecha el orden: compara el valor del medio y descarta la mitad que no puede contener la respuesta. El número de comparaciones crece de forma logarítmica, pero solo porque la suposición de orden es cierta. Ordenar solo para una búsqueda puede costar más que recorrer una vez.

La búsqueda binaria vale la pena cuando los datos ya están ordenados o cuando muchas búsquedas reutilizan ese orden. Identifica cuánto cuesta mantener el orden a medida que llegan registros nuevos.

Define el intervalo con precisión

Es más fácil razonar sobre una implementación cuando su región de candidatos está definida con precisión.

Con un intervalo semiabierto [lo, hi), lo está incluido y hi está excluido, así que la región queda vacía cuando lo es igual a hi. El bucle se repite mientras lo < hi: si el valor del medio es demasiado pequeño, haz lo = mid + 1; si no, haz hi = mid. Cada iteración debe reducir la región sin descartar una respuesta válida posible. bisect_left de Python devuelve la posición de inserción antes de los valores iguales que ya existan.

No promete que exista un valor que coincida. Compara el índice devuelto con la longitud de la colección y revisa el elemento antes de afirmar que la búsqueda tuvo éxito.

Python
from bisect import bisect_left

ids = [10, 20, 20, 40]
i = bisect_left(ids, 20)
found = i < len(ids) and ids[i] == 20
print(i, found)

Buscar es una decisión de diseño

La respuesta que quieres cambia el algoritmo.

¿Quieres cualquier ID que coincida, el primer duplicado, todos los duplicados o la siguiente hora programada después de un umbral? Deja claro ese contrato antes de elegir código. Prueba una colección vacía, un objetivo antes del primer elemento, uno después del último y los duplicados.

En Relay, un calendario ordenado podría encontrar eficientemente el primer trabajo futuro, pero insertar en una lista de Python sigue desplazando elementos. Una búsqueda rápida no hace rápida toda la estructura de datos.

ERROR FRECUENTE

Tratar una posición de inserción como prueba de una coincidencia, o ignorar el costo O(n) de insertar en una lista ordenada de Python.

INTÉNTALO TÚ

Para [2, 5, 5, 9], predice las posiciones de bisect_left para 1, 5, 8 y 10. Identifica cuáles corresponden a coincidencias reales.

COMPROBACIÓN DE RECUERDO / APLICA LA IDEA

Decide en el laboratorio.

El checkpoint de dos preguntas, tus notas y tu progreso guardado están en el laboratorio. Gratis y sin cuenta.

Abrir en el laboratorio ↗

CONÉCTALO CON RELAY

Implementa una búsqueda de trabajos programados de Relay y anota si devuelve un trabajo, un punto de inserción o ambos.