DEV Community

Martin Pi
Martin Pi

Posted on

Big-O en Español - Parte 2

En el post previo, revisamos la notación de Big-O para expresiones lineales y constantes. En este post vamos a explorar las expresiones cuadráticas y cómo se comportan las funciones elevadas a cualquier potencia.


¿Qué encontrarás en esta serie?

  1. Parte 1: Expresiones Lineales y Constantes

    Introducción a las notaciones más simples y cómo afectan el rendimiento de nuestros algoritmos.

  2. Parte 2: Expresiones Cuadráticas, Cúbicas y de Otras Potencias

    Un análisis más profundo sobre cómo crecen los tiempos de ejecución en algoritmos más complejos.

  3. [Parte 3: Expresiones Logarítmicas, Exponenciales y Factoriales]

    Exploraremos casos donde el tiempo de ejecución crece de forma mucho más drástica.

  4. [Parte 4: Combinando Complejidades y Comparando Estructuras de Datos]

    Analizaremos cómo diferentes estructuras de datos afectan la complejidad y cómo combinar varios algoritmos.

  5. [Parte 5: Consideraciones Avanzadas y Casos Reales]

    Reflexiones finales sobre trade-offs entre tiempo y espacio, complejidades amortizadas, y cómo aplicar Big-O en escenarios reales.


Expresiones Cuadráticas

Vamos a ilustrar esta notación con un ejemplo práctico.

Supongamos que tenemos un arreglo con todas las selecciones de fútbol masculino que han salido campeonas del mundo desde 1930. Este arreglo incluye el nombre del país tantas veces como mundiales ganó:

const campeonesMundiales = ["Uruguay", "Italia", "Italia", "Uruguay", "Alemania",
                            "Brasil", "Brasil", "Inglaterra", "Brasil", "Alemania", "Argentina",
                            "Italia", "Argentina", "Alemania", "Brasil", "Francia",
                            "Italia", "España", "Alemania", "Francia"];
Enter fullscreen mode Exit fullscreen mode

Ahora supongamos que tenemos otro arreglo con todas las selecciones que participaron en el Mundial de Qatar 2022:

const seleccionesQatar = ["Qatar", "Alemania", "Dinamarca", "Brasil", "Francia",
                          "Paises Bajos", "Argentina", "Iran", "Corea del Sur", "Japon", "Arabia Saudita",
                          "Ecuador", "Uruguay", "Canada", "Ghana", "Senegal", "Marruecos", "Tunez", "Portugal",
                          "Polonia", "Camerun", "Mexico", "Estados Unidos", "Gales", "Australia", "Costa Rica"];
Enter fullscreen mode Exit fullscreen mode

Queremos averiguar cuáles de estas selecciones han sido campeonas del mundo y cuántas veces.

Código

El siguiente código realiza esta tarea:

function listarCampeones() {
    for (let i = 0; i < seleccionesQatar.length; i++) {
        const seleccion = seleccionesQatar[i];
        let count = 0;

        for (let j = 0; j < campeonesMundiales.length; j++) {
            if (seleccion === campeonesMundiales[j]) {
                count++;
            }
        }

        console.log(`La selección ${seleccion} ${(count === 0 ? "no ha salido campeona del mundo" : `ha ganado ${count} mundial(es)`)}.`);
    }
}
Enter fullscreen mode Exit fullscreen mode

En este código, por cada selección que participa en Qatar, verificamos cada entrada en el arreglo de campeones del mundo. Esto implica dos bucles anidados, lo que resulta en una complejidad cuadrática.

Complejidad Matemática

Cada bucle tiene una complejidad lineal O(n). Al combinarlos, obtenemos:

f(x) = x * x = x²
Enter fullscreen mode Exit fullscreen mode

Esto significa que el tiempo de ejecución crece proporcionalmente al cuadrado del tamaño de los arreglos. Cuanto más grandes sean los arreglos, más tiempo llevará procesar todas las combinaciones.


Expresiones Cúbicas y Potencias Mayores

Si añadimos más bucles anidados al algoritmo, seguimos multiplicando la complejidad lineal. Por ejemplo:

  • Tres bucles anidados:
f(x) = x * x * x = x³
Enter fullscreen mode Exit fullscreen mode
  • Cuatro bucles anidados:
f(x) = x * x * x * x = x⁴
Enter fullscreen mode Exit fullscreen mode

Representación Gráfica

A continuación, una gráfica que muestra cómo el tiempo de ejecución se incrementa con el tamaño de los datos en funciones cuadráticas y de mayor potencia:

Image description

Como se observa, las potencias más altas hacen que el tiempo de procesamiento crezca de manera exponencial, lo que puede llevar a tiempos de ejecución inaceptables.


Recomendaciones

Para optimizar algoritmos con bucles anidados:

  1. Reducir bucles innecesarios: Evita iteraciones redundantes que puedan ser optimizadas.
  2. Usar estructuras de datos eficientes: Por ejemplo, emplear tablas hash puede reducir búsquedas lineales o cuadráticas a búsquedas constantes (O(1)).
  3. Dividir y conquistar: Algoritmos como quicksort y mergesort usan este enfoque para reducir la complejidad.

Conclusión

En este post, exploramos las expresiones cuadráticas y el impacto de las potencias mayores en la complejidad computacional. Estas notaciones son esenciales para identificar problemas de escalabilidad en algoritmos.

En la próxima parte, hablaremos de otros tipos de expresiones, como las logarítmicas, exponenciales y factoriales. ¡No te lo pierdas!

Top comments (0)