El análisis de complejidad es una parte fundamental en el estudio de algoritmos, ya que nos permite evaluar la eficiencia de un algoritmo en términos de tiempo y espacio. En esta sección, aprenderemos los conceptos básicos de la complejidad temporal y espacial, cómo se mide y cómo se expresa utilizando la notación Big O.
Conceptos Básicos
Complejidad Temporal
La complejidad temporal se refiere a la cantidad de tiempo que un algoritmo tarda en completarse en función del tamaño de la entrada. Es crucial para determinar la eficiencia de un algoritmo, especialmente cuando se trabaja con grandes conjuntos de datos.
Complejidad Espacial
La complejidad espacial se refiere a la cantidad de memoria que un algoritmo necesita para ejecutarse en función del tamaño de la entrada. Esto incluye tanto la memoria utilizada por las variables como la memoria adicional que el algoritmo pueda requerir.
Notación Big O
La notación Big O es una forma de expresar la complejidad de un algoritmo de manera asintótica, es decir, cómo se comporta el algoritmo cuando el tamaño de la entrada tiende a infinito.
Principales Clases de Complejidad
-
O(1) - Constante: El tiempo de ejecución no depende del tamaño de la entrada.
def constante_algo(arr): return arr[0]
-
O(log n) - Logarítmica: El tiempo de ejecución crece logarítmicamente con el tamaño de la entrada.
import math def logaritmica_algo(n): return math.log(n)
-
O(n) - Lineal: El tiempo de ejecución crece linealmente con el tamaño de la entrada.
def lineal_algo(arr): for i in arr: print(i)
-
O(n log n) - Linealítmica: El tiempo de ejecución crece en función de n log n.
def linealitmica_algo(arr): arr.sort()
-
O(n^2) - Cuadrática: El tiempo de ejecución crece cuadráticamente con el tamaño de la entrada.
def cuadratica_algo(arr): for i in arr: for j in arr: print(i, j)
-
O(2^n) - Exponencial: El tiempo de ejecución crece exponencialmente con el tamaño de la entrada.
def exponencial_algo(n): if n == 0: return 1 else: return exponencial_algo(n-1) + exponencial_algo(n-1)
Ejemplos Prácticos
Ejemplo 1: Búsqueda Lineal vs. Búsqueda Binaria
Búsqueda Lineal (O(n))
Búsqueda Binaria (O(log n))
def busqueda_binaria(arr, x): low = 0 high = len(arr) - 1 while low <= high: mid = (low + high) // 2 if arr[mid] == x: return mid elif arr[mid] < x: low = mid + 1 else: high = mid - 1 return -1
Ejemplo 2: Ordenación por Burbuja vs. Ordenación Rápida
Ordenación por Burbuja (O(n^2))
def ordenacion_burbuja(arr): n = len(arr) for i in range(n): for j in range(0, n-i-1): if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j] return arr
Ordenación Rápida (O(n log n))
def ordenacion_rapida(arr): if len(arr) <= 1: return arr pivot = arr[len(arr) // 2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return ordenacion_rapida(left) + middle + ordenacion_rapida(right)
Ejercicios Prácticos
Ejercicio 1: Análisis de Complejidad
Analiza la complejidad temporal de los siguientes fragmentos de código:
Soluciones
- O(n): El bucle
for
recorre todos los elementos dearr
una vez. - O(n^2): El bucle
for
anidado recorre todos los elementos dearr
para cada elemento dearr
.
Ejercicio 2: Implementación de Algoritmos
Implementa una función que realice la búsqueda binaria en una lista ordenada y otra que realice la ordenación por burbuja.
Soluciones
- Búsqueda Binaria
def busqueda_binaria(arr, x): low = 0 high = len(arr) - 1 while low <= high: mid = (low + high) // 2 if arr[mid] == x: return mid elif arr[mid] < x: low = mid + 1 else: high = mid - 1 return -1
- Ordenación por Burbuja
def ordenacion_burbuja(arr): n = len(arr) for i in range(n): for j in range(0, n-i-1): if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j] return arr
Conclusión
En esta sección hemos aprendido los conceptos básicos del análisis de complejidad, incluyendo la complejidad temporal y espacial, y cómo se expresa utilizando la notación Big O. También hemos visto ejemplos prácticos y realizado ejercicios para reforzar estos conceptos. Con esta base, estamos preparados para profundizar en técnicas algorítmicas más avanzadas en los siguientes módulos.
Algoritmos Avanzados
Módulo 1: Introducción a los Algoritmos Avanzados
Módulo 2: Algoritmos de Optimización
- Programación Lineal
- Algoritmos de Optimización Combinatoria
- Algoritmos Genéticos
- Optimización de Colonia de Hormigas
Módulo 3: Algoritmos en Grafos
- Representación de Grafos
- Búsqueda en Grafos: BFS y DFS
- Algoritmos de Caminos Mínimos
- Algoritmos de Flujo Máximo
- Algoritmos de Emparejamiento en Grafos
Módulo 4: Algoritmos de Búsqueda y Ordenación
Módulo 5: Algoritmos de Aprendizaje Automático
- Introducción al Aprendizaje Automático
- Algoritmos de Clasificación
- Algoritmos de Regresión
- Redes Neuronales y Deep Learning
- Algoritmos de Clustering
Módulo 6: Casos de Estudio y Aplicaciones
- Optimización en la Industria
- Aplicaciones de Grafos en Redes Sociales
- Búsqueda y Ordenación en Grandes Volúmenes de Datos
- Aplicaciones de Aprendizaje Automático en la Vida Real