14/07/2022
En el mundo de la informática y el desarrollo de software, la eficiencia es un pilar fundamental. Escribir un código que no solo resuelva un problema, sino que lo haga de la manera más rápida y con el menor consumo de recursos posible, es lo que diferencia a un buen programador. Aquí es donde entra en juego el análisis de complejidad de algoritmos, una herramienta esencial para medir y predecir el rendimiento de nuestro código. Una de las complejidades más interesantes y eficientes es la logarítmica, y en particular, la complejidad log-lineal o N log N. En este artículo, desglosaremos en profundidad qué es la complejidad logarítmica, cómo se calcula, sus diferentes variantes y por qué es tan crucial para algoritmos de alto rendimiento.

¿Qué es la Complejidad Temporal Logarítmica?
Para entender la complejidad logarítmica, primero debemos tener claros dos conceptos: el logaritmo y el análisis de complejidad.

Entendiendo el Logaritmo
Un logaritmo, en términos sencillos, es la potencia a la que se debe elevar una base para obtener un número determinado. Por ejemplo, el logaritmo en base 2 de 8 es 3, porque 2 elevado a la potencia de 3 es igual a 8 (2³ = 8). En el análisis de algoritmos, la base del logaritmo a menudo es 2, ya que muchos algoritmos eficientes funcionan dividiendo el problema a la mitad en cada paso, un enfoque conocido como divide y vencerás.
La característica principal de una función logarítmica es que crece muy lentamente. Mientras el tamaño de la entrada (N) aumenta exponencialmente, el número de operaciones solo aumenta linealmente. Esta es la clave de su eficiencia.
Análisis de Complejidad: Midiendo la Eficiencia
El análisis de complejidad es el proceso de determinar cuán eficientemente un algoritmo resuelve un problema. Se mide principalmente en dos dimensiones:
- Complejidad Espacial: La cantidad de memoria que un algoritmo necesita para ejecutarse en función del tamaño de la entrada.
- Complejidad Temporal: La cantidad de tiempo (o número de operaciones) que un algoritmo tarda en completarse en función del tamaño de la entrada.
Para estandarizar esta medición, utilizamos la notación asintótica, que describe el comportamiento del algoritmo a medida que el tamaño de la entrada tiende al infinito. Las más comunes son:
- Big-O (O): Representa el peor de los casos, un límite superior del tiempo de ejecución.
- Big-Omega (Ω): Representa el mejor de los casos, un límite inferior.
- Big-Theta (Θ): Representa el caso promedio, cuando el mejor y el peor caso coinciden.
En la práctica, la notación Big-O es la más utilizada, ya que nos prepara para el escenario más desfavorable, garantizando que el rendimiento del algoritmo no superará ese límite.
Órdenes de Complejidad Comunes
Para poner en perspectiva la complejidad logarítmica, es útil compararla con otros órdenes de complejidad comunes. A continuación, se presenta una tabla que ordena las complejidades de la más eficiente a la menos eficiente.
| Notación | Nombre | Descripción |
|---|---|---|
| O(1) | Constante | El tiempo de ejecución es el mismo, sin importar el tamaño de la entrada. |
| O(log N) | Logarítmica | El tiempo de ejecución crece muy lentamente a medida que aumenta la entrada. |
| O(N) | Lineal | El tiempo de ejecución es directamente proporcional al tamaño de la entrada. |
| O(N log N) | Log-lineal | Una combinación de tiempo lineal y logarítmico. Muy común en algoritmos de ordenamiento eficientes. |
| O(N²) | Cuadrática | El tiempo de ejecución es proporcional al cuadrado del tamaño de la entrada (bucles anidados). |
| O(2^N) | Exponencial | El tiempo de ejecución se duplica con cada adición a la entrada. Muy ineficiente. |
| O(N!) | Factorial | El tiempo de ejecución crece de forma factorial. Prácticamente inviable para entradas de tamaño moderado. |
Profundizando en las Variantes de la Complejidad Logarítmica
La complejidad logarítmica no es un término único; existen varias formas que aparecen en diferentes tipos de algoritmos. Analicemos las más importantes.

O(log N) - Complejidad Logarítmica Simple
Esta es la forma más pura de complejidad logarítmica. Un algoritmo con esta complejidad reduce significativamente el conjunto de datos en cada paso. El ejemplo clásico es la búsqueda binaria. Si tienes un arreglo ordenado de un millón de elementos, en el peor de los casos, solo necesitarás unas 20 comparaciones (log₂(1,000,000) ≈ 19.9) para encontrar un elemento, en lugar de un millón de comparaciones con una búsqueda lineal.
O(N log N) - Complejidad Log-lineal
Esta es una de las complejidades más importantes en la informática. Se encuentra en algoritmos que aplican una operación logarítmica (O(log N)) para cada uno de los N elementos de la entrada. Los algoritmos de ordenamiento más eficientes, como Merge Sort, Quick Sort (en su caso promedio) y Heap Sort, tienen esta complejidad. Realizan N operaciones, y cada una de ellas implica un proceso de división y conquista que toma tiempo logarítmico.
O(log log N) - Complejidad Doble Logarítmica
Esta complejidad es aún más eficiente que O(log N). Es extremadamente rara, pero aparece en algoritmos muy especializados, como la búsqueda interpolada en datos uniformemente distribuidos o en ciertas estructuras de datos avanzadas. El crecimiento es increíblemente lento.
Otras Variantes
- O(log² N): El cuadrado del logaritmo de N. Crece más rápido que O(log N) pero mucho más lento que O(N).
- O(N² log N): Se puede encontrar en algoritmos que, por ejemplo, ordenan N filas de una matriz de N x N, donde ordenar cada fila toma O(N log N).
Ejemplos Prácticos para Entender la Complejidad
Veamos cómo se manifiestan estas complejidades en el código.
Ejemplo 1: Reducción de un número - O(log N)
Imagina una tarea simple: dado un número N, ¿cuántas veces puedes dividirlo por 2 hasta que llegue a 1? Este proceso es inherentemente logarítmico.

// Pseudocódigo para demostrar O(log N)función reducirNumero(N) { operaciones = 0; mientras (N > 1) { N = N / 2; operaciones = operaciones + 1; } retornar operaciones;}// Si N = 16, el bucle se ejecutará 4 veces (16 -> 8 -> 4 -> 2).// log₂(16) = 4.Ejemplo 2: Búsqueda Binaria - O(log N)
Como mencionamos, este es el ejemplo por excelencia. En un arreglo ordenado, en cada paso, el algoritmo compara el elemento buscado con el elemento del medio. Si no es el que busca, descarta la mitad del arreglo donde el elemento no puede estar y repite el proceso con la mitad restante.
// Pseudocódigo para Búsqueda Binariafunción busquedaBinaria(arreglo, elementoBuscado) { inicio = 0; fin = longitud(arreglo) - 1; mientras (inicio <= fin) { medio = piso((inicio + fin) / 2); si (arreglo[medio] == elementoBuscado) { retornar medio; // Encontrado } sino si (arreglo[medio] < elementoBuscado) { inicio = medio + 1; // Buscar en la mitad derecha } sino { fin = medio - 1; // Buscar en la mitad izquierda } } retornar -1; // No encontrado}Ejemplo 3: Merge Sort - O(N log N)
Merge Sort es un algoritmo de ordenamiento que sigue la estrategia "divide y vencerás".
- Divide: Divide el arreglo de N elementos en dos mitades de N/2 elementos de forma recursiva hasta que queden arreglos de un solo elemento. Este proceso de división crea una estructura de árbol con una altura de log N.
- Vence: Combina (merge) las dos mitades ordenadas para crear una sola versión ordenada. Este paso de combinación requiere recorrer todos los N elementos.
El resultado es que en cada nivel del "árbol" de recursión (que son log N niveles), se realizan N operaciones de combinación. Por lo tanto, la complejidad total es O(N log N).
Comparativa de Crecimiento: ¿Por qué es tan importante?
Para visualizar la diferencia drástica en el rendimiento, comparemos el número de operaciones para diferentes valores de N.
| Tamaño de Entrada (N) | O(log N) | O(N) | O(N log N) | O(N²) |
|---|---|---|---|---|
| 10 | ~3 | 10 | ~33 | 100 |
| 100 | ~7 | 100 | ~664 | 10,000 |
| 1,000 | ~10 | 1,000 | ~9,965 | 1,000,000 |
| 1,000,000 | ~20 | 1,000,000 | ~19,931,568 | 1,000,000,000,000 |
Como se puede observar, mientras que un algoritmo O(N²) se vuelve intratable rápidamente (un billón de operaciones para una entrada de un millón), un algoritmo O(N log N) se mantiene completamente manejable. La diferencia es abismal y crucial para aplicaciones que manejan grandes volúmenes de datos.

Preguntas Frecuentes (FAQ)
¿Por qué la base del logaritmo no suele importar en la notación Big O?
La notación Big O se centra en la tasa de crecimiento e ignora los factores constantes. Gracias a la fórmula de cambio de base de los logaritmos (logₐ(x) = logᵦ(x) / logᵦ(a)), podemos convertir un logaritmo de una base a otra multiplicándolo por una constante (1 / logᵦ(a)). Dado que Big O ignora las constantes, log₂(N), log₁₀(N) o ln(N) se agrupan todos bajo la misma complejidad O(log N).
¿Qué es mejor, O(log N) u O(N)?
Para tamaños de entrada suficientemente grandes, O(log N) es significativamente mejor y más eficiente que O(N). Un algoritmo logarítmico escala mucho mejor a medida que los datos crecen, ya que el tiempo de ejecución aumenta muy lentamente en comparación con un algoritmo lineal.
¿Cuáles son las "leyes de los logaritmos" más importantes para el análisis de algoritmos?
Tres propiedades son fundamentales:
- Regla del Producto: log(x*y) = log(x) + log(y)
- Regla del Cociente: log(x/y) = log(x) - log(y)
- Regla de la Potencia: log(x^k) = k * log(x). Esta es especialmente útil para analizar bucles que modifican su contador de forma multiplicativa o divisoria.
¿El valor de log(1) siempre es cero?
Sí. Por definición, cualquier base 'a' elevada a la potencia 0 es igual a 1 (a⁰ = 1). Por lo tanto, el logaritmo de 1 en cualquier base válida (positiva y distinta de 1) es siempre cero. Esto tiene sentido en algoritmos: si el tamaño del problema es 1, a menudo se resuelve en un número constante de pasos, que en la escala logarítmica corresponde a cero.
Conclusión
Comprender la complejidad algorítmica, especialmente las complejidades logarítmicas como O(log N) y O(N log N), es indispensable para cualquier desarrollador de software serio. No se trata solo de un concepto teórico, sino de una herramienta práctica que impacta directamente en la escalabilidad, la velocidad y la experiencia del usuario de una aplicación. Los algoritmos con complejidad logarítmica son la columna vertebral de muchas de las operaciones más comunes que realizamos a diario, desde buscar en una base de datos hasta ordenar una lista de contactos. Dominar su análisis y aplicación te permitirá escribir un código no solo funcional, sino verdaderamente eficiente y profesional.
Si quieres conocer otros artículos parecidos a Guía Completa de la Complejidad N log N puedes visitar la categoría Automovilismo.
