El peor costo de una operación individual no siempre representa el costo de una secuencia. El análisis amortizado distribuye operaciones ocasionalmente caras entre muchas operaciones baratas y ofrece una garantía para cualquier secuencia válida, sin asumir una distribución probabilística.
También debes evaluar trade-offs: reducir tiempo puede exigir memoria, preprocesamiento, complejidad de código o garantías más débiles.
Los benchmarks miden una implementación concreta; el análisis asintótico explica cómo escala una familia de entradas. Se complementan, no se sustituyen.
Una hash table puede duplicar buckets y reinsertar n entradas en O(n). Si crece geométricamente, el trabajo total de todos los rehashes durante n inserciones es O(n).
El lookup sigue siendo promedio, no garantizado, por las colisiones. Son dos análisis distintos:
Con una consulta pequeña, construir el índice puede ser innecesario. Con muchas, domina el ahorro.
La decisión también depende de actualizaciones. Un índice estático puede requerir reconstrucción; una estructura dinámica añade costos de mantenimiento.
Una operación amortizada O(1) puede tener picos O(n). Para una aplicación interactiva o de tiempo real, el throughput total puede ser bueno y aun así la latencia máxima ser inaceptable.
Opciones:
reservar capacidad;
crecimiento incremental;
estructuras con peor caso garantizado;
repartir rehashing entre operaciones;
evitar pausas grandes de GC.
Big O amortizado no responde por sí solo requisitos de latencia.
No sumes toda memoria creada a lo largo del tiempo si se libera antes de crear la siguiente. La complejidad espacial suele medir el máximo simultáneo.
En recursión:
llamadas secuenciales pueden liberar frames;
profundidad máxima define stack activo;
resultados retenidos pueden impedir liberar memoria.
En merge sort, buffers por niveles pueden reutilizarse. Una implementación con slices crea más asignaciones totales, pero el pico debe analizarse según qué referencias siguen vivas.
correctitud
→ restricciones de n
→ operaciones dominantes
→ tiempo esperado y peor caso
→ memoria y pico
→ mutación y estabilidad
→ complejidad de implementación
→ medición representativa
Una solución teóricamente óptima puede no ser la mejor si es difícil de mantener, si la entrada es pequeña o si una librería ofrece una implementación probada.
¿Por qué un push amortizado O(1) todavía puede ser problemático en un sistema con límites estrictos de latencia?
Respuesta
Porque una operación concreta puede disparar una expansión y copiar n elementos. El costo total de muchas operaciones es bueno, pero el pico individual puede superar el límite de latencia.