0% encontró este documento útil (0 votos)
257 vistas4 páginas

Complejidad de Algoritmos

Apunte básico

Cargado por

isela
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
257 vistas4 páginas

Complejidad de Algoritmos

Apunte básico

Cargado por

isela
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Complejidad de Algoritmos

La complejidad de algoritmos se refiere al número de recursos (tiempo y/o espacio) que


un algoritmo necesita para resolver un problema, en función del tamaño de la entrada. La
complejidad es un concepto fundamental en la ciencia de la computación, ya que nos ayuda
a evaluar la eficiencia de un algoritmo y a comparar diferentes soluciones para el mismo
problema.

Existen dos tipos principales de complejidad que se estudian:

1. Complejidad temporal: Mide el tiempo que tarda un algoritmo en ejecutarse, en


función del tamaño de la entrada.
2. Complejidad espacial: Mide la cantidad de memoria o espacio adicional que un
algoritmo necesita durante su ejecución, en función del tamaño de la entrada.

El análisis de la complejidad de algoritmos se realiza utilizando la notación asintótica, que


describe el comportamiento del algoritmo para entradas de tamaño muy grande (cuando n
tiende al infinito). Las notaciones más comunes para describir la complejidad son:

● O (notación O-grande): Representa el peor caso.


● Ω (notación Omega): Representa el mejor caso.
● Θ (notación Theta): Representa el caso promedio o el comportamiento en general
del algoritmo.

En este apunte, nos centraremos en O (notación O-grande), que es la más utilizada en el


análisis de complejidad, ya que describe la cota superior del tiempo o espacio requerido
por un algoritmo.

1. Complejidad Temporal: Notación O-grande

La notación O-grande se utiliza para clasificar los algoritmos según la cantidad de tiempo
que requieren a medida que el tamaño de la entrada crece. El análisis de la complejidad
temporal permite determinar la eficiencia de un algoritmo en función de cómo aumenta su
tiempo de ejecución con el tamaño de los datos.

Principales complejidades temporales


O(1) - Tiempo constante: Un algoritmo con complejidad O(1) siempre toma el mismo
tiempo, independientemente del tamaño de la entrada. Este tipo de complejidad se observa
en algoritmos cuyo tiempo de ejecución no depende del número de elementos de la
entrada.
Ejemplo: Acceder a un elemento en una lista por su índice:
python
Copiar código
def acceso_elemento(lista, indice):
return lista[indice]
● Comportamiento: El tiempo de ejecución es siempre constante, sin importar el
tamaño de la lista.

O(log n) - Tiempo logarítmico: Un algoritmo con complejidad O(log n) se ejecuta en tiempo


proporcional al logaritmo del tamaño de la entrada. Esto ocurre cuando el problema se
divide en mitades sucesivas en cada paso, como en la búsqueda binaria.
Ejemplo: Búsqueda binaria en una lista ordenada:
python
Copiar código
def busqueda_binaria(lista, valor):
inicio, fin = 0, len(lista) - 1
while inicio <= fin:
medio = (inicio + fin) // 2
if lista[medio] == valor:
return medio
elif lista[medio] > valor:
fin = medio - 1
else:
inicio = medio + 1
return -1

● Comportamiento: La lista se divide a la mitad en cada iteración, lo que da como


resultado una complejidad logarítmica.

O(n) - Tiempo lineal: Un algoritmo con complejidad O(n) toma un tiempo proporcional al
tamaño de la entrada. Esto es común en algoritmos que recorren todos los elementos de
una lista o array de manera secuencial.
Ejemplo: Búsqueda lineal:
python
Copiar código
def busqueda_lineal(lista, valor):
for i in range(len(lista)):
if lista[i] == valor:
return i
return -1

● Comportamiento: Recorre todos los elementos de la lista, por lo que el tiempo de


ejecución aumenta linealmente con el número de elementos.

O(n log n) - Tiempo log-lineal: La complejidad O(n log n) es común en algoritmos de


ordenamiento eficientes, como el Merge Sort y el Quick Sort. Estos algoritmos dividen el
problema en subproblemas más pequeños y los resuelven eficientemente.
Ejemplo: Algoritmo de ordenamiento Merge Sort:
python
Copiar código
def merge_sort(lista):
if len(lista) <= 1:
return lista
medio = len(lista) // 2
izquierda = merge_sort(lista[:medio])
derecha = merge_sort(lista[medio:])
return merge(izquierda, derecha)

● Comportamiento: El algoritmo divide repetidamente la lista y luego fusiona las


sublistas, lo que da como resultado una complejidad O(n log n).

O(n²) - Tiempo cuadrático: Un algoritmo con complejidad O(n²) toma tiempo proporcional
al cuadrado del tamaño de la entrada. Este tipo de complejidad es común en algoritmos de
ordenamiento ineficientes como el Ordenamiento por burbuja (Bubble Sort) o
Selección.
Ejemplo: Ordenamiento por burbuja:
python
Copiar código
def burbuja(lista):
for i in range(len(lista)):
for j in range(len(lista) - i - 1):
if lista[j] > lista[j + 1]:
lista[j], lista[j + 1] = lista[j + 1], lista[j]

● Comportamiento: El algoritmo compara elementos adyacentes en múltiples


pasadas, lo que da como resultado un tiempo cuadrático.

O(2^n) - Tiempo exponencial: Un algoritmo con complejidad O(2^n) es muy ineficiente y


aumenta rápidamente con el tamaño de la entrada. Este tipo de complejidad se encuentra
comúnmente en algoritmos de fuerza bruta que exploran todas las combinaciones posibles.
Ejemplo: Algoritmo recursivo para resolver el problema de la serie de Fibonacci de
manera ineficiente:
python
Copiar código
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

● Comportamiento: La cantidad de llamadas recursivas crece exponencialmente con


el tamaño de n.

2. Complejidad Espacial: Notación O-grande


La complejidad espacial se refiere a la cantidad de memoria adicional que un algoritmo
necesita para ejecutarse. Similar a la complejidad temporal, se clasifica utilizando la
notación O-grande.

Ejemplos comunes de complejidad espacial:

● O(1): Un algoritmo con complejidad espacial O(1) utiliza una cantidad constante de
memoria, independientemente del tamaño de la entrada. Por ejemplo, un algoritmo
que solo usa variables temporales o punteros.
● O(n): Un algoritmo con complejidad espacial O(n) requiere espacio proporcional al
tamaño de la entrada. Esto puede ocurrir cuando se necesita almacenar todos los
elementos de la entrada, como en el caso de algunos algoritmos de ordenamiento o
búsqueda.

3. Análisis de Complejidad: ¿Por qué es Importante?

El análisis de la complejidad de un algoritmo es crucial para:

● Predecir el rendimiento: Ayuda a entender cómo un algoritmo se comportará con


entradas grandes.
● Optimización: Permite identificar cuellos de botella en el rendimiento y elegir
algoritmos más eficientes.
● Escalabilidad: Es esencial para garantizar que un algoritmo pueda manejar grandes
volúmenes de datos o cargas de trabajo sin un impacto negativo significativo en el
tiempo de ejecución o el uso de memoria.

El análisis de la complejidad de algoritmos es fundamental para entender cómo los


programas se comportan en términos de tiempo y espacio, especialmente a medida que el
tamaño de la entrada aumenta. Los algoritmos eficientes son clave para desarrollar software
que sea rápido y escalable. Al aprender a evaluar la complejidad temporal y espacial, los
programadores pueden elegir las soluciones más adecuadas para sus problemas y escribir
código más optimizado y eficiente.

También podría gustarte