En esta lección fijamos las bases de la complejidad algorítmica y de la notación Big-O. El objetivo es entender qué medimos, por qué lo hacemos y cómo impacta en el código que escribimos en Python.
La complejidad describe cómo crece el consumo de recursos a medida que aumenta el tamaño de entrada n. Nos enfocamos en:
O(f(n)).O(f(n)) para distinguir si es constante, lineal o mayor.La notación Big-O expresa la cota superior asintótica, es decir, el ritmo de crecimiento dominante a grandes n.
Medir la complejidad permite tomar decisiones de diseño informadas:
Sin esta mirada, es fácil elegir una solución que funcione en casos pequeños pero colapse en producción.
El análisis asintótico ignora constantes y asume un modelo ideal; el tiempo real depende de hardware y del entorno. Dos ejemplos:
O(n) con constantes grandes puede tardar más que uno O(n log n) para tamaños pequeños.Podemos medir en Python con un bucle simple y contadores de pasos:
def contar_pasadas(datos):
pasos = 0
for dato in datos:
pasos += 1 # lectura del dato
if dato % 2 == 0:
pasos += 1 # comparación extra
return pasos # modelo teórico de pasos ejecutados
El código refleja un modelo de pasos. Para tiempo real usaríamos temporizadores del sistema, pero el orden de crecimiento sigue siendo O(n).
Elegir un modelo aclara qué operaciones cuentan como un paso:
En este tutorial partimos del modelo RAM y señalamos cuando otros modelos cambian las conclusiones.
Trabajar en Python permite centrarse en la lógica y evaluar el impacto de las estructuras:
Estas ideas guiarán los temas siguientes, donde profundizaremos en la notación, los tipos de complejidad temporal y espacial, y las formas de medirlos en práctica.