Big O no mide segundos ni premia el código corto. Describe cómo crece el trabajo cuando crece la entrada, y permite descartar una solución lenta antes de ejecutarla.
Un algoritmo puede tardar un milisegundo con diez datos y volverse inutilizable con un
millón. Medirlo una vez no alcanza. Lo que importa es cómo crece el trabajo cuando crece
la entrada, y eso es lo que intenta capturar la notación Big O.
Qué se cuenta, ya que no son segundos
No contamos segundos porque dependen de la máquina, el lenguaje y lo que esté ejecutándose
al mismo tiempo. Contamos operaciones relevantes en función del tamaño de entrada n.
const contains = (values: number[], target: number): boolean => { for (const value of values) { if (value === target) return true; } return false;};
En el peor caso, contains mira los n elementos. Si duplicamos la cantidad de datos,
duplicamos aproximadamente el trabajo. Decimos que su tiempo crece como O(n).
Por qué sobrevive sólo el término dominante
Supongamos que una cuenta exacta da
T(n)=3n2+20n+500.
Para entradas grandes, n2 domina a n y a la constante. Big O conserva esa forma de
crecimiento y descarta coeficientes:
T(n)∈O(n2).
No significa que las constantes nunca importen. Importan al optimizar un sistema real.
Significa que una constante no puede salvar un crecimiento peor para siempre: por muy
rápido que sea hoy un algoritmo cuadrático, uno lineal termina ganándole cuando n crece.
La escalera de las familias comunes
Las familias más comunes forman una escalera:
Orden
Cuando n se duplica
Ejemplo típico
O(1)
casi igual
acceso por índice
O(logn)
suma un paso
búsqueda binaria
O(n)
se duplica
recorrer una lista
O(nlogn)
un poco más del doble
mergesort
O(n2)
se cuadruplica
comparar todos contra todos
O(2n)
se eleva al cuadrado
explorar subconjuntos
La diferencia se vuelve brutal rápido. Con n=1.000.000, log2n ronda 20; n2 es
un billón. No son optimizaciones pequeñas: son problemas de otra escala.
Antes de seguir, predecí
Orden
Operaciones
A mil millones por segundo
Dónde aparece
O(1)
1
1.0 ns
Acceder a un índice
O(log n)
4
4.3 ns
Búsqueda binaria
O(n)
20
20 ns
Recorrer una lista
O(n log n)
86
86 ns
Mergesort
O(n²)
400
400 ns
Comparar todos contra todos
O(2ⁿ)
1.048.576
1.0 ms
Probar todos los subconjuntos
Movés n y mirás en qué momento cada curva se despega. La columna de tiempo es lo que tardaría una máquina que hace mil millones de operaciones por segundo.
Un ciclo no es automáticamente O(n)
Un ciclo no implica automáticamente O(n) y dos ciclos no implican automáticamente
O(n2). Hay que mirar cuántas veces corre cada uno.
Dos ciclos consecutivos de n pasos hacen n+n=2n, que sigue siendo O(n). Dos ciclos
anidados de n pasos hacen n⋅n=n2. Pero si el índice se duplica en cada vuelta,
el ciclo corre sólo log2n veces. La sintaxis se parece; la progresión del índice es
la que decide el costo.
De dónde sale un logaritmo
La búsqueda binaria trabaja sobre datos ordenados. En cada comparación descarta la mitad
de lo que queda. Después de k pasos quedan n/2k candidatos. Cuando queda uno,
2kn=1⇒k=log2n.
Esa ecuación explica O(logn) mejor que memorizarlo. La base del logaritmo no aparece
en Big O porque cambiar de base sólo multiplica por una constante.
Antes de anunciar una complejidad, decir qué es n
Antes de anunciar una complejidad hay que decir qué representa n. En un grafo suelen
importar dos tamaños, vértices V y aristas E; un recorrido cuesta O(V+E). En una
matriz rectangular importan filas y columnas; recorrerla cuesta O(f⋅c).
Reducir todo a una sola letra puede esconder el dato que realmente crece. “Es lineal” no
alcanza: lineal ¿en usuarios, mensajes, píxeles o conexiones entre nodos?
O, Omega y Theta: tres cosas distintas
Formalmente, O(g(n)) es una cota superior: para entradas suficientemente grandes, el
costo no crece más rápido que una constante por g(n). Ω(g(n)) es una cota
inferior y Θ(g(n)) indica que ambas coinciden.
En conversaciones de programación se usa “es O(n)” para decir “crece linealmente”, que
formalmente sería Θ(n). La distinción importa en demostraciones, pero en una
entrevista o revisión de código suele importar más declarar el caso analizado y justificar
el conteo.
Lo que la notación esconde
n
O(log n)
O(n)
O(n log n)
O(n²)
O(2ⁿ)
10
3
10
33
100
1.024
100
7
100
664
10.000
10³⁰
1.000
10
1.000
9.966
10⁶
no entra en el universo
1.000.000
20
10⁶
2 × 10⁷
10¹²
—
La última fila es la que fija la intuición: con un millón de elementos, lineal y n log n son prácticamente lo mismo, y cuadrático son diez mil segundos de cómputo. La frontera práctica está entre n log n y n².
Cierre
Big O no adivina rendimiento: elimina soluciones que no pueden escalar. Definí el tamaño
de entrada, contá cómo avanza el algoritmo y quedate con el crecimiento dominante. Después
medí constantes y hardware. Primero elegís una familia viable; recién entonces optimizás
sus detalles.