Un algoritmo puede acertar y aun así ser demasiado lento, o ser rápido y dar una respuesta incorrecta. Primero separaremos esas dos obligaciones. Después elegiremos qué tamaño tiene la entrada y qué operación cuesta una unidad; solo entonces tendrá sentido comparar crecimiento lineal, cuadrático o logarítmico.
Si necesitas repasar:
1. Antes de medir tiempo hay que demostrar qué hace el algoritmo
El problema define entradas permitidas y respuestas válidas. El algoritmo especifica los pasos. La corrección parcial dice que, si termina, entrega una respuesta válida. Para corrección total se demuestra además que termina en toda entrada permitida. Acertar en varias pruebas sirve para detectar fallos, pero no sustituye esa garantía.
Un invariante es una afirmación que vale al inicio y se conserva al repetir un bucle. Junto a la condición de salida demuestra la respuesta. Para terminar se usa, por ejemplo, una medida entera no negativa que disminuye estrictamente en cada repetición. Hay que comprobar inicio, conservación, salida y terminación, no solo nombrarlos.
Encontrar el máximo sin favorecer el cero
Entrada no vacía [−4,−1,−7]. Se inicia M en el primer dato y se recorren los restantes.
Invariante
Tras procesar i datos, M es el máximo de los primeros i.
Conservar
El siguiente paso reemplaza M por el mayor entre M y el dato nuevo; la afirmación sigue siendo cierta.
Salida
Se pasa de −4 a −1 y se conserva −1 al leer −7; al terminar i=n, M es el máximo de toda la lista.
Terminar
n−i baja uno por cada dato pendiente y nunca es negativo.
El resultado es −1 y el argumento vale para cualquier lista no vacía.
Inicializar M=0 devolvería cero en este ejemplo, aunque cero no aparezca: un contraejemplo basta para refutar esa versión.
El invariante de una suma empieza en la lista vacía
Se inicia s=0 y se añade cada elemento de [3,−2,5].
Inicio
Antes de leer nada, s es la suma de cero datos: cero.
Conservación
Añadir el siguiente valor convierte la suma del prefijo anterior en la del nuevo prefijo.
Salida y límite
Los acumulados son 3,1,6; tras tres pasos no quedan datos.
La suma es seis; para una lista de longitud n se usan n incorporaciones al acumulador.
La misma inicialización también permite la entrada vacía, que devuelve cero.
2. El tamaño de un entero no es su valor
Para una lista, n suele ser el número de elementos. Para un entero positivo N escrito en binario, su longitud es b=⌊log₂N⌋+1 bits. Un algoritmo que hace N pasos puede ser exponencial respecto a b, aunque parezca lineal al usar N como variable.
En un modelo unitario se cuentan comparaciones, accesos o sumas como una operación cuando los operandos caben en palabras apropiadas. Si los números crecen sin cota, ese modelo no describe el coste de bits. La suma escolar de b bits necesita recorrer como máximo b posiciones y un acarreo; la multiplicación escolar realiza un orden cuadrático de operaciones de bits.
No se concluye que todos los algoritmos de multiplicación tengan ese coste.
Contar hasta el valor puede ser muy caro para su descripción
N=1024 en binario es un uno seguido de diez ceros.
Longitud
Su representación tiene b=11 bits.Recorrido
Visitar todos los enteros de 1 a N hace 1024 pasos, no once.
Escala general
Entre enteros de b bits, N está entre 2ᵇ⁻¹ y 2ᵇ−1; ese recorrido tiene coste Θ(2ᵇ).
Es lineal en el valor N y exponencial en la longitud binaria b.
Hay que declarar la variable de tamaño antes de decir “lineal”.
Una operación aritmética puede ocultar muchos pasos
Se suman dos enteros de un millón de bits con el método escolar.
Modelo unitario idealizado
Contar una suma como una operación oculta la longitud de los operandos.
Modelo de bits
Se procesan las columnas y los acarreos: O(b) trabajo para b bits.
Almacenamiento
El resultado puede necesitar b+1 bits, no una palabra fija independiente de b.
Para números grandes, el coste debe incluir la longitud que se manipula.
El modelo unitario es útil con tamaños de palabra justificados; no es una garantía física de suma constante para cualquier entero.
3. Tiempo, memoria auxiliar y memoria acumulada no son la misma medida
T(n) cuenta trabajo; S(n) cuenta memoria máxima ocupada al mismo tiempo. Se declara si incluye entrada y salida o solo espacio auxiliar. Guardar resultados intermedios puede reducir trabajo repetido y aumentar memoria. Sumar todo lo reservado y liberado durante una ejecución no mide necesariamente el máximo simultáneo.
La recursión mantiene llamadas pendientes en una pila. Su profundidad y lo guardado en cada llamada cuentan aunque el código no declare un arreglo. Si se copian sublistas, esas copias también importan; pasar intervalos de una lista evita confundir una descripción de subproblema con una copia completa.
Leer todos los datos puede necesitar poca memoria extra
Se busca el máximo de una lista almacenada de n números que caben en una palabra.
Tiempo
Hay n−1 comparaciones con el máximo actual.
Auxiliar
Basta un índice y un máximo: O(1) palabras auxiliares.
Entrada
La lista ya almacenada ocupa Θ(n) palabras, si se incluye en la medida.
El tiempo es Θ(n) y el espacio auxiliar O(1).
No se dice espacio total constante ignorando la entrada que permanece almacenada.
La profundidad no es el número total de llamadas
Un recorrido recursivo de un árbol binario completo guarda una cantidad constante de información por llamada y explora una rama cada vez.
Profundidad
Con altura h hay como máximo h+1 llamadas pendientes.
Total
Puede visitar todos los n vértices y hacer Θ(n) trabajo.
Memoria
En el árbol equilibrado h=Θ(log n), la pila ocupa O(log n) espacio auxiliar, sin contar el árbol.
La suma de visitas puede ser lineal y la pila máxima logarítmica.
En una cadena de n vértices la profundidad sería Θ(n); el equilibrio es una hipótesis relevante.
4. O acota por arriba; Θ declara un orden ajustado
Con costes no negativos y g positiva desde cierto umbral, T=O(g) significa que existen C>0 y n₀ con T(n)≤Cg(n) para todo n≥n₀. Ω usa una cota inferior cg(n), c>0. Θ exige ambas. Las constantes se eligen una vez, no dependen de n.
Una función puede tener varias cotas superiores: T(n)=n pertenece a O(n), O(n²) y O(2ⁿ), pero estas últimas son menos precisas. Escribir O no afirma que la cota sea óptima ni una igualdad exacta de operaciones. Los términos de menor orden no cambian Θ si se justifican las dos cotas.
Dar constantes concretas demuestra una Θ
T(n)=2n+10 para n≥1.
Inferior
T(n)≥2n.Superior desde un umbral
Para n≥10, 10≤n, así T(n)≤3n.Definición
c=2, C=3, n₀=10 prueban T=Θ(n).
El coste crece linealmente aunque no sea exactamente n.
Que también sea O(n²) no vuelve cuadrático su orden ajustado.
Acotar un polinomio completo
T(n)=n²+3n+2.
Por debajo
T(n)≥n² para n≥1.Por arriba
3n≤3n² y 2≤2n², de modo que T(n)≤6n².Conclusión
c=1, C=6, n₀=1 prueban Θ(n²).
El término cuadrático da el orden ajustado.
La cota superior seis es suficiente para la prueba; no necesita ser la menor constante posible.
5. Peor caso, promedio y amortizado requieren preguntas diferentes
El peor caso maximiza el coste entre entradas de igual tamaño y el mejor lo minimiza. El promedio necesita una distribución explícita de entradas. No se obtiene promediando sin más las dos cifras extremas: las probabilidades de cada caso deciden el resultado.
El análisis amortizado reparte el coste total de una secuencia de operaciones. No necesita azar: puede garantizar un coste medio por operación para cualquier secuencia válida. Una operación particular puede ser cara y el total seguir siendo pequeño porque esas operaciones caras no pueden ocurrir continuamente.
Búsqueda secuencial con una distribución declarada
Buscamos un elemento que aparece una vez en una lista de n posiciones, todas equiprobables.
Casos extremos
Si está primero se usa una comparación; si está último, n.
Promedio justificado
La esperanza es (1+2+⋯+n)/n=(n+1)/2 por la distribución uniforme.Otra distribución
Si falta con probabilidad 1/2 y, cuando está, su posición es uniforme, la esperanza es n/2+(n+1)/4=(3n+1)/4.
El promedio cambia al cambiar la distribución, incluso con los mismos extremos de coste.
La coincidencia del primer promedio con la media de extremos ocurre por esta simetría particular; no es la definición general.
Amortizar copias al duplicar un arreglo
Capacidad inicial uno; al llenarse se duplica. Contamos una unidad por dato copiado y otra por dato añadido.
Cinco inserciones
Las copias al crecer son 1+2+4=7; las escrituras nuevas son cinco: total doce.
Secuencia general
Las capacidades anteriores forman una geométrica 1+2+4+⋯ menor que 2N tras N inserciones.
Total
Copias más N escrituras son menos que 3N; el coste amortizado es O(1) por inserción.
Una inserción puede copiar Θ(N) datos, pero cualquier secuencia de N tiene coste total O(N) en este modelo.
Se declaró qué se cuenta; incluir un coste proporcional a capacidad reservada mantiene O(N), aunque cambiaría la constante concreta.
6. Los límites de cada bucle determinan la suma
Un bucle con n repeticiones de trabajo constante cuesta Θ(n). Dos bucles consecutivos suman; uno dentro de otro exige sumar cuántos pasos internos se hacen para cada valor exterior. Si el interior tiene siempre n pasos, la suma es n·n; si tiene i, la suma es 1+⋯+n.
La sumatoria escribe límites e índice para que no se pierdan filas. Para 1+⋯+n, escribir la suma en ambos sentidos da n pares de valor n+1; dividir por dos produce n(n+1)/2. Si el cuerpo cuesta i en vez de una unidad, ese trabajo también entra dentro de la suma.
El triángulo de cuatro filas no es un cuadrado
i recorre 1,…,4 y, para cada i, j recorre 1,…, i.
Filas
Las longitudes son 1,2,3,4.
Exacto
Hay 1+2+3+4=10 ejecuciones del cuerpo.General
Para n filas son n(n+1)/2; entre n²/2 y n² para n≥1, así Θ(n²).
La cuenta exacta es diez para cuatro filas, no dieciséis.
Mismo orden asintótico no significa mismo número exacto de operaciones.
Consecutivos y anidados no se multiplican igual
Comparamos dos bucles separados de n pasos con un bucle n×n.
Separados
El primero termina y luego comienza el segundo: n+n=2n trabajos.
Anidados
Por cada una de n vueltas exteriores se hacen n interiores: n².
Ejemplo
Para n=3 los totales son seis y nueve, respectivamente.
Los separados son Θ(n) y los anidados completos Θ(n²).
Si el cuerpo de cada vuelta fuese más costoso que una unidad, habría que sumarlo además.
7. Las mitades se cuentan con logaritmos, bajo hipótesis de acceso y orden
Con n=2ᵏ, reducir a la mitad k veces deja uno: n/2ᵏ=1. Para la regla abstracta s←⌈s/2⌉ hasta s=1, el máximo de reducciones es ⌈log₂n⌉. Es una cuenta de cambios de tamaño, no una cifra universal de comparaciones para todo código de búsqueda binaria.
La búsqueda binaria usa una lista ordenada y acceso al elemento central con el coste supuesto. Tras comparar, descarta una parte conservando todos los candidatos que podrían contener el objetivo. En una lista enlazada, llegar al centro puede costar más; si hay que ordenar antes, ese trabajo se suma.
Logaritmos de bases fijas mayores que uno difieren por un factor constante.
Seguir los cambios de tamaño
Partimos de 32 candidatos y hacemos mitades exactas hasta uno.
Secuencia
32,16,8,4,2,1.
Cambios
Son seis tamaños, pero cinco reducciones.
Logaritmo
32=2⁵, así log₂32=5.
Hacen falta cinco reducciones.
Para un único candidato ya hay cero reducciones, aunque el programa pueda necesitar compararlo con el objetivo.
Redondear hacia arriba conserva el caso más grande
Regla s←⌈s/2⌉ para s inicial 35.
Seguir
35→18→9→5→3→2→1.Contar
Hay seis cambios.
Potencias
2⁵=32<35≤64=2⁶, así ⌈log₂35⌉=6.
El máximo abstracto es seis reducciones.
Esta regla de tamaños se declaró explícitamente; una implementación puede excluir el centro y tener otra cuenta exacta de comparaciones.
8. Un árbol de llamadas suma trabajo por niveles
En T(n)=2T(n/2)+n, con T(1)=1 y n potencia de dos, cada llamada crea dos mitades. El primer nivel trabaja n; el siguiente, 2·n/2=n; el siguiente vuelve a sumar n. Hay log₂n niveles internos y n hojas de coste uno. El total exacto es n log₂n+n.
Si el trabajo de combinación está entre constantes positivas por n, el argumento da Θ(n log n). Con tamaños generales se fijan suelos, techos y caso base; los niveles cambian en sus bordes pero mantienen el orden para la división equilibrada usual. Una sola llamada por nivel no tiene el mismo árbol y puede costar mucho menos.
Sumar el árbol del dibujo
T(n)=2T(n/2)+n, T(1)=1; n=8.
Niveles internos
8;4+4;2+2+2+2: cada uno cuesta ocho.
Hojas
Ocho llamadas de tamaño uno cuestan ocho.
Total
8·3+8=32; por la regla también T(2)=4 y T(4)=12, luego T(8)=32.
T(8)=32 y el orden general es Θ(n log n).
La profundidad es tres, pero hay muchas llamadas por nivel: no se cuenta solo una rama.
Una sola mitad cambia la recurrencia
T(n)=T(n/2)+1 con T(1)=1 y n=2ᵏ.
Desplegar
Cada paso añade uno y conserva una sola llamada.
Profundidad
Tras k pasos se llega a T(1).
Total
T(2ᵏ)=k+1; para n=8 da cuatro.
El orden es Θ(log n), con el coste base incluido.
El uno adicional explica por qué tiempo total y número de reducciones pueden diferir en una constante.
9. Una cota de un programa no demuestra un límite de todo el problema
Las constantes pueden decidir qué algoritmo conviene en entradas pequeñas. Medir tiempos complementa el análisis, pero depende del equipo, implementación y entradas. “Polinómico” respecto a longitud significa O(nᵏ) para algún exponente fijo; ni una constante enorme ni un exponente enorme garantizan viabilidad práctica.
Mostrar que un algoritmo tarda Θ(n²) no prueba que todos los que resuelven el problema deban hacerlo. Para una cota inferior del problema se considera cualquier algoritmo dentro de un modelo declarado. Un argumento de información puede demostrar límites del modelo de comparaciones, sin trasladarlos automáticamente a otros modelos.
Las constantes pueden invertir al ganador
Comparamos costes A(n)=1000n y B(n)=n².
n=100
A cuesta 100000 y B 10000: B es menor.
n=2000
A cuesta 2000000 y B 4000000: A es menor.
Cruce
1000n=n² para n positivo da n=1000.
El algoritmo lineal gana finalmente, pero no en todo tamaño.
Las fórmulas son costes declarados del ejemplo, no tiempos reales universales de los algoritmos lineales y cuadráticos.
Un método lento no limita a todos los métodos
Se ordenan n datos mediante un método cuadrático; existe también mezcla con Θ(n log n) en el modelo de comparaciones adecuado.
Primera cota
Θ(n²) describe el primer algoritmo.
Contraejemplo a una imposibilidad
El segundo resuelve el mismo problema con crecimiento menor.
Alcance
La lentitud del primero no demuestra una cota inferior cuadrática del problema.
Para hablar de imposibilidad hay que razonar sobre todos los algoritmos permitidos, no uno.
El modelo debe conservarse en la comparación: coste de comparaciones y coste de bits no se intercambian.
Una cota inferior por información sí considera cualquier árbol de comparación
Ordenar n elementos distintos usando comparaciones de dos resultados.
Resultados posibles
Hay n! órdenes que el algoritmo debe distinguir.
Árbol de decisiones
Con altura h puede tener como máximo 2ʰ hojas; se requiere 2ʰ≥n!.
Despejar
h≥log₂(n!).Los últimos aproximadamente n/2 factores de n! son al menos n/2, así log₂(n!)=Ω(n log n).
Todo algoritmo de ese modelo necesita Ω(n log n) comparaciones en algún caso.
La conclusión está restringida al modelo de comparaciones; no contradice métodos que usan estructura adicional de claves y otras operaciones.
Ahora lo resolvemos de principio a fin.
EJEMPLO RESUELTO 1
Dos bucles
Se ejecuta una operación por cada par (i,j) con 1≤i,j≤n.
Objeto contado
Cada ejecución corresponde a un par ordenado (i, j), con ambos índices entre uno y n.
Primer índice
Hay n elecciones posibles de i.
Continuaciones
Para cada una, j recorre las n posibilidades completas.
Exacto
El producto n·n=n² cuenta cada par una vez.
Asintótico
Una operación por par produce Θ(n²) en el modelo indicado.
Comprobar
Para n=1 hay un par y para n=2 hay cuatro; duplicar n cuadruplica este recuento.
Θ(n²).
Para n=1 hay una operación y para n=2 hay cuatro; el producto cuenta pares, sin omitir ninguno.
EJEMPLO RESUELTO 2
Búsqueda binaria
Máximo de mitades necesarias para reducir 1024 candidatos a uno.
Tamaño inicial
Se parte de 1024 candidatos.
Potencia
1024=2¹⁰.Cada reducción
Tras k mitades ideales quedan 1024/2ᵏ candidatos.
Final
Para quedar uno se necesita 2ᵏ=1024, así k=10.Secuencia
1024,512,256,128,64,32,16,8,4,2,1: once tamaños y diez cambios.
Alcance
Son diez reducciones del intervalo, no una afirmación de diez comparaciones exactas para cualquier implementación.
Diez reducciones.
La secuencia de tamaños es1024,512,256,128,64,32,16,8,4,2,1: once tamaños y diez transiciones.
Los símbolos que hemos usado
- n
- Tamaño de entrada, definido según el problema.
- T(n)
- Cantidad de operaciones contadas para entradas de tamaño n, en el caso especificado.
- O(g(n))
- Cota superior asintótica por un múltiplo constante de g.
- Ω(g(n))
- Cota inferior asintótica por un múltiplo positivo de g.
- Θ(g(n))
- Cotas superior e inferior del mismo orden g.
- S(n)
- Espacio utilizado; debe precisarse si incluye entrada o solo memoria auxiliar.
- log₂n
- Logaritmo de base2, adecuado al contar reducciones a la mitad.
Ahora te toca a ti.
Tienes cinco ejercicios. Inténtalos; las pistas te ayudan si te atascas.
Practicar este tema →