Mirá este fragmento de código:
Leer(a)
n ← a * a
c ← 0
MIENTRAS (a > 1) HACER
a ← a / 2
PARA i = 1 HASTA n HACER
c ← c * 2
¿Cuál es la complejidad de este código? ¿Por qué?
Ver solución
Aclaración importante antes de empezar
El código usa la variable n para un valor calculado (n ← a * a), pero en notación Big-O normalmente usamos "" para referirnos al tamaño de la entrada. Para no confundirnos, en este análisis vamos a llamar al tamaño de la entrada (el dato que se lee con Leer(a)), y dejamos que la variable interna del programa siga llamándose , sabiendo que .
Paso 1: Instrucciones simples (fuera de los bucles)
n ← a * a
c ← 0
Estas dos líneas se ejecutan una sola vez, sin importar el tamaño de . Son operaciones de costo constante:
Dato clave: se calcula una única vez, antes de entrar al bucle MIENTRAS, y su valor queda fijo en durante toda la ejecución (no se vuelve a recalcular, aunque cambie después). Esto es crucial para el análisis que sigue.
Paso 2: Analizar el bucle MIENTRAS (externo)
MIENTRAS (a > 1) HACER
a ← a / 2
...
En cada iteración, se divide por 2. Partiendo del valor inicial , la secuencia de valores es:
Esto es exactamente la misma lógica que la búsqueda binaria: ¿cuántas veces hay que dividir por 2 hasta llegar a 1? La respuesta es:
Entonces, el bucle MIENTRAS se ejecuta veces.
Paso 3: Analizar el bucle PARA (interno)
PARA i = 1 HASTA n HACER
c ← c * 2
Este bucle se ejecuta desde hasta . Como vimos en el Paso 1, y no cambia durante toda la ejecución del programa (aunque sí cambie). Entonces, cada vez que entramos al bucle PARA, se ejecuta operaciones de costo constante ().
Paso 4: Combinar ambos bucles
El bucle PARA está anidado dentro del bucle MIENTRAS. Como el bucle interno hace siempre la misma cantidad de trabajo en cada pasada (porque no cambia), simplemente multiplicamos