0% encontró este documento útil (0 votos)
197 vistas20 páginas

Análisis de Algoritmos y Complejidad

El documento aborda el análisis de algoritmos y la complejidad computacional, destacando la importancia de los algoritmos en la resolución de problemas y su aplicación en diversas industrias. Se exploran conceptos fundamentales como la definición de algoritmos, su análisis en términos de tiempo y espacio, y la clasificación de problemas según su dificultad. Además, se discute la notación asintótica como herramienta clave para evaluar la eficiencia y escalabilidad de los algoritmos.

Cargado por

pofifew842
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)
197 vistas20 páginas

Análisis de Algoritmos y Complejidad

El documento aborda el análisis de algoritmos y la complejidad computacional, destacando la importancia de los algoritmos en la resolución de problemas y su aplicación en diversas industrias. Se exploran conceptos fundamentales como la definición de algoritmos, su análisis en términos de tiempo y espacio, y la clasificación de problemas según su dificultad. Además, se discute la notación asintótica como herramienta clave para evaluar la eficiencia y escalabilidad de los algoritmos.

Cargado por

pofifew842
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

Análisis de Algoritmos y Complejidad Computacional: Fundamentos, Medidas y

Clases de Problemas

Introducción

Los algoritmos constituyen la esencia de la computación moderna, definidos


fundamentalmente como un "conjunto ordenado y finito de operaciones que permite
hallar la solución de un problema".1 Estos procedimientos secuenciales, un conjunto de
reglas precisas para ejecutar una tarea o resolver una cuestión, preceden incluso la
invención de los ordenadores, habiendo sido empleados por la humanidad en diversas
formas desde tiempos remotos.2 En el ámbito de la informática, los algoritmos son la
"columna vertebral" que dicta a las máquinas las instrucciones exactas y el orden en
que deben ejecutarlas.2 Los programas informáticos, en su esencia, son algoritmos
codificados en lenguajes de programación.2
La presencia de los algoritmos es ubicua en la vida diaria y en la industria. Se
manifiestan en sistemas tan variados como los motores de búsqueda que organizan la
información (por ejemplo, el algoritmo de Google) 1, las redes sociales que personalizan
la experiencia del usuario (como EdgeRank de Facebook) 1, y las plataformas de
recomendación que sugieren contenido o productos (como Netflix, Spotify, Amazon y
YouTube).2 Su aplicación se extiende a dominios críticos como la detección de fraude
financiero, la evaluación del riesgo crediticio en la banca, la optimización de rutas
logísticas y la mejora de la eficiencia energética industrial.3
El análisis de algoritmos surge como una disciplina fundamental para evaluar el
rendimiento de estas secuencias de operaciones. Se centra en la evaluación teórica de
un algoritmo en términos de su tiempo de ejecución y el espacio de memoria que
consume, ambos en función del tamaño de la entrada.5 Este estudio es crucial para
comprender la eficiencia del software, permitiendo optimizar el código y reducir los
recursos necesarios para ejecutar un programa.5 La capacidad de determinar el
algoritmo más idóneo para un problema específico, considerando sus complejidades
temporales y espaciales, es una de las principales metas del análisis algorítmico.6
Además, este conocimiento es vital para evitar el consumo innecesario de recursos, lo
que es indispensable para el desarrollo de soluciones de software escalables y
sostenibles.6
Una comprensión profunda del análisis de algoritmos revela que estos no son
meramente herramientas computacionales; se han convertido en el motor de la nueva
revolución industrial.2 Su influencia trasciende el ámbito de la informática, permeando
diversas industrias. La capacidad de los algoritmos para procesar vastas cantidades de
información en el menor tiempo posible y automatizar análisis complejos que serían
abrumadores para una persona 3 transforma los datos brutos en conocimientos
accionables. Esto no se limita a la creación de software más rápido, sino que habilita la
toma de decisiones basada en datos, la optimización de procesos complejos del mundo
real y la emergencia de nuevos modelos de negocio.3 Esta transformación implica que
el pensamiento algorítmico y su análisis ya no son exclusivos de los departamentos de
ciencias de la computación, sino que se están convirtiendo en competencias esenciales
para la estrategia empresarial, la eficiencia operativa y la ventaja competitiva en un
amplio espectro de sectores.
Este informe se adentrará en los fundamentos del análisis de algoritmos, las métricas
clave para su evaluación, las herramientas matemáticas empleadas en su estudio, y la
clasificación de los problemas computacionales según su dificultad inherente.
1. Análisis de Algoritmos: Conceptos Fundamentales

1.1. Definición y Características de un Algoritmo

Un algoritmo es una secuencia finita y ordenada de instrucciones bien definidas que, al


ser ejecutadas, resuelven un problema o logran un objetivo específico.1 La concepción
de un algoritmo es un paso de diseño fundamental que precede a la elaboración del
código informático.1 Es en esta fase donde se determina la lógica y el método para
resolver el problema, haciendo que el proceso de codificación posterior sea, en muchos
casos, una traducción mecánica de esa lógica.8 Esta distinción subraya que el desafío
intelectual central en la resolución de problemas en ciencias de la computación reside
en idear el algoritmo, es decir, la secuencia lógica de pasos, más que en su mera
traducción a un lenguaje de programación. Un algoritmo elegante y eficiente, incluso si
su implementación no es óptima, generalmente superará a un algoritmo
fundamentalmente ineficiente, por muy bien codificado que esté.
Todo algoritmo se compone de tres elementos esenciales 1:
●​ Input (Entrada): Los datos necesarios para que el algoritmo comience su
ejecución y encuentre la solución esperada.
●​ Proceso: Las operaciones que el algoritmo realiza con la información de entrada.
●​ Output (Salida): Los resultados obtenidos una vez que el algoritmo ha completado
su procesamiento, proporcionando la solución al problema planteado.
Las características que definen a un algoritmo son cruciales para su funcionalidad y
fiabilidad 1:
●​ Definidos: Ante la misma información de entrada, un algoritmo debe producir
siempre los mismos resultados, garantizando la consistencia.
●​ Concretos: Deben ofrecer una solución específica y unívoca al problema.
●​ Finitos: Un algoritmo no puede prolongarse indefinidamente; debe tener un
número determinado de pasos tras los cuales finaliza.
●​ Ordenados: La secuencia de sus pasos debe ser clara y concisa para asegurar el
éxito en la resolución del problema.
●​ Precisos: Las instrucciones deben ser inequívocas y directas hacia la solución, sin
ambigüedades.
Los algoritmos pueden clasificarse de diversas maneras según su naturaleza y la forma
en que abordan los problemas 1:
●​ Cualitativos: Se basan en secuencias lógicas y no requieren cálculos numéricos.
●​ Cuantitativos: Articulan el proceso de solución a través de cálculos matemáticos
sobre datos numéricos.
●​ Computacionales: Requieren de una computadora para su implementación,
generalmente debido a la complejidad o el volumen de cálculos.
●​ No Computacionales: Pueden ser resueltos por una persona sin necesidad de un
ordenador.
●​ Según su estrategia de diseño: Incluyen algoritmos de "divide y vencerás" (que
descomponen un problema en subproblemas más pequeños del mismo tipo), de
"fuerza bruta" (que prueban todas las soluciones posibles), de "programación
dinámica" (que resuelven subproblemas una vez y almacenan sus soluciones para
reutilizarlas), de "ordenación" (que organizan elementos en un orden específico),
"voraces" (que toman decisiones localmente óptimas con la esperanza de
encontrar una solución global óptima) y "probabilísticos" o "aleatorios" (que utilizan
la aleatoriedad como parte de su lógica para optimizar el tiempo o la calidad de la
solución).2

1.2. Propósito e Importancia del Análisis de Algoritmos en la Informática y la


Ingeniería de Software

El análisis de algoritmos es el estudio de la complejidad computacional de los


algoritmos.7 Su objetivo principal es determinar el comportamiento de los algoritmos en
términos de los recursos que consumen, principalmente tiempo de procesamiento y
espacio de memoria.10 Esta evaluación es teórica y se realiza en función del tamaño de
la entrada del problema.5
La relevancia del análisis de algoritmos en la informática y la ingeniería de software es
multifacética:
●​ Optimización del Rendimiento: Permite comprender cómo hacer el código más
eficiente, reduciendo el tiempo de ejecución y el espacio de memoria necesarios
para un programa.6
●​ Escalabilidad: Al entender cómo se comporta un algoritmo a medida que aumenta
el tamaño de la entrada, los desarrolladores pueden diseñar soluciones que
escalen adecuadamente con el crecimiento del problema, garantizando su
viabilidad en escenarios de gran volumen de datos.7
●​ Utilización Eficiente de Recursos: Los algoritmos eficientes consumen menos
potencia de procesamiento y memoria. Esto se traduce directamente en menores
costos computacionales y un uso más sostenible de la infraestructura tecnológica.6
●​ Mejor Toma de Decisiones: El análisis proporciona un marco objetivo para
comparar diferentes algoritmos y estructuras de datos que resuelven el mismo
problema. Esto facilita la selección de la solución más adecuada, considerando las
restricciones de rendimiento y recursos.6
●​ Verificación de Correctitud y Viabilidad: Permite probar formalmente que un
algoritmo producirá la respuesta correcta para todas las entradas posibles.8
Además, ayuda a comprender la viabilidad práctica de un algoritmo para un
problema determinado.6
●​ Impacto Económico y Competitivo: Empresas líderes en la industria tecnológica,
como Google, Amazon y Facebook, invierten considerablemente en el análisis y la
optimización de sus algoritmos. Incluso mejoras marginales en la eficiencia de un
algoritmo pueden generar ahorros masivos en costos computacionales y mejorar
significativamente la experiencia del usuario a escala global, lo que impacta
directamente en su competitividad.3

2. Recursos Computacionales y Estudio de la Complejidad


2.1. Definición de Complejidad Computacional

La complejidad computacional es una rama fundamental de la ciencia de la


computación que se dedica a clasificar los algoritmos en función de la cantidad de
recursos computacionales que requieren para su ejecución.5 Este campo de estudio es
esencial para comprender los límites inherentes y las capacidades prácticas de los
sistemas informáticos.6

2.2. Recursos Principales: Tiempo de Procesamiento y Espacio de Memoria

Los dos recursos principales considerados en la complejidad computacional son 5:


●​ Tiempo de Procesamiento (Tiempo de Ejecución): Se refiere al tiempo que un
algoritmo tarda en completar su tarea. Se expresa como una función, T(n), que
representa el número de operaciones básicas realizadas en relación con el tamaño
de la entrada n.5 El interés principal no es el tiempo exacto en segundos, sino la
tasa de crecimiento de​
T(n) a medida que n aumenta.5
●​ Espacio de Memoria: Se refiere a la cantidad de memoria que un algoritmo
necesita para almacenar datos y variables durante su ejecución.5
Un principio importante en el diseño de algoritmos es el balance espacio/tiempo.8 A
menudo, es posible intercambiar uno por el otro para optimizar el rendimiento general.
Por ejemplo, un algoritmo podría usar más memoria para almacenar resultados
intermedios y así reducir el tiempo de cálculo, o viceversa.

2.3. Modelos de Máquina y Conteo de Operaciones Básicas

El análisis de algoritmos se fundamenta en un modelo de computación abstracto,


comúnmente el Modelo de Máquina de Acceso Aleatorio (RAM).5 Este modelo
idealizado asume que cada operación elemental, como las operaciones aritméticas,
lógicas, asignaciones de variables o el acceso a una posición de memoria, se ejecuta
en un tiempo constante.5
La abstracción que proporciona el modelo RAM es crucial porque establece un entorno
computacional estandarizado e idealizado que desvincula el análisis algorítmico de las
particularidades del hardware real y de las instrucciones de bajo nivel de la máquina.
Los ordenadores del mundo real varían en sus arquitecturas de CPU, jerarquías de
memoria (cachés, RAM, disco) y conjuntos de instrucciones. Medir directamente las
operaciones en una máquina específica podría no ser representativo para otra. Sin un
modelo común, la comparación de algoritmos sería inconsistente, requiriendo
reevaluaciones constantes para cada nueva iteración de hardware o lenguaje de
programación. El modelo RAM permite a los científicos de la computación concentrarse
en la eficiencia inherente de la lógica del algoritmo, en lugar de la eficiencia transitoria
de su ejecución en una máquina particular. Esta abstracción es fundamental para la
rigurosidad teórica y la aplicabilidad práctica del análisis de complejidad, posibilitando
predicciones sobre cómo un algoritmo escalará, independientemente del hardware
subyacente, siempre que ese hardware se ajuste a las suposiciones del modelo RAM.
Esto asegura que el análisis conserve su relevancia a medida que la tecnología
avanza.
En el análisis teórico, se calcula matemáticamente el número de operaciones
fundamentales que realiza un algoritmo, en lugar de depender de mediciones empíricas
de rendimiento.5 Para ello, se cuantifican las "instrucciones básicas", que son líneas de
código que ejecutan un número constante de operaciones elementales. Las llamadas a
funciones y los bucles (
for, while) se evalúan sumando el número de instrucciones básicas que contienen.11
Por ejemplo, para una función sum_list que calcula la suma de los elementos de una
lista de longitud N, el conteo de operaciones básicas sería el siguiente 11:

Python

def sum_list(lst):​
total = 0 # 1 instrucción básica​
for value in lst:​
total += value # ejecutado N veces (una por cada elemento)​
return total # 1 instrucción básica​

El número total de instrucciones básicas es 1 + N + 1 = N + 2. Al simplificar esto para el


análisis de complejidad, se obtiene una complejidad de O(N).

2.4. Análisis de Casos: Mejor Caso, Peor Caso y Caso Promedio

El análisis de algoritmos considera cómo se comporta un algoritmo en diferentes


escenarios de entrada 5:
●​ Mejor Caso: Representa la situación más favorable para el algoritmo, donde el
tiempo de ejecución es mínimo. Por ejemplo, en un algoritmo de ordenación de
burbuja, el mejor caso ocurre cuando los elementos ya están ordenados,
resultando en un tiempo de ejecución lineal, O(n).5 Este escenario, sin embargo, es
menos útil en la práctica porque es poco probable que ocurra con frecuencia.11
●​ Peor Caso: Describe la situación más desfavorable, donde el tiempo de ejecución
es máximo. Este es el enfoque más común y valioso en el análisis de complejidad,
ya que garantiza que el algoritmo nunca tendrá un rendimiento inferior a un umbral
determinado.5 Para el ordenamiento de burbuja, el peor caso se da cuando los
elementos están en orden inverso, llevando a un tiempo de ejecución cuadrático,
O(n^2).5
●​ Caso Promedio: Evalúa el rendimiento esperado del algoritmo bajo una
distribución típica de entradas. Aunque su cálculo es más complejo, puede ofrecer
una visión más realista del comportamiento del algoritmo en condiciones
habituales.

3. Medidas Asintóticas y Órdenes de Complejidad


3.1. Notación Asintótica: Herramienta para Describir la Eficiencia

La notación asintótica es una herramienta matemática esencial utilizada para describir


la eficiencia de los algoritmos, centrándose en su comportamiento cuando el tamaño de
la entrada es muy grande.5 Su propósito principal no es determinar los valores
absolutos de las funciones de tiempo o espacio, sino caracterizar la eficiencia y permitir
la comparación relativa entre diferentes algoritmos, independientemente de las
condiciones específicas de implementación (como el lenguaje de programación, el
compilador o el hardware).12 Esta notación analiza la tasa de crecimiento de las
funciones en el límite, es decir, cómo aumentan los recursos requeridos a medida que
la entrada se hace infinitamente grande.12
La notación asintótica funciona como un "contrato de escalabilidad" o una "garantía de
rendimiento" para los algoritmos. Permite a desarrolladores e investigadores comunicar
y predecir cómo se comportará un algoritmo bajo una carga creciente, sin la necesidad
de realizar pruebas de rendimiento en cada posible configuración de hardware.
Conocer que un algoritmo es, por ejemplo, O(N log N) permite predecir que, si el
tamaño de la entrada se duplica, el tiempo de ejecución también se duplicará
aproximadamente (más un pequeño factor logarítmico), sin importar si N es 100 o 10
mil millones. Esto es más valioso que un tiempo de ejecución exacto en milisegundos
en una máquina específica. Esta capacidad predictiva guía las decisiones de diseño; si
un problema involucra conjuntos de datos potencialmente enormes, un algoritmo
O(N^2) podría ser descartado de inmediato en favor de uno O(N log N), incluso si el
primero es más sencillo para entradas pequeñas.11 La notación asintótica transforma el
análisis de algoritmos de una medición empírica a una ciencia teórica, proporcionando
un marco robusto para razonar sobre la eficiencia y tomar decisiones de ingeniería
informadas. Es el lenguaje a través del cual se comprenden los límites y el potencial
inherente de las soluciones computacionales.
Las tres notaciones asintóticas principales son:

3.1.1. Notación O Grande (Big O - O(·))

●​ Definición: Una función f(n) pertenece a O(g(n)) si existen constantes positivas c y


n0 tales que f(n) ≤ c * g(n) para todo n ≥ n0.12
●​ Propósito: Expresa una cota superior asintótica, indicando el crecimiento
máximo del tiempo de ejecución en el peor caso.5 Describe el límite superior de los
requisitos de tiempo de ejecución o espacio de un algoritmo.6
●​ Intuición Práctica: El algoritmo no será peor que g(n) en su tasa de crecimiento
para entradas grandes.
●​ Ejemplos: 6n³ ∈ O(n³) (con c=6, n0=1), 3 logn ∈ O(n) (con c=1, n0=4), 2ⁿ ∈
O(n!).12

3.1.2. Notación Omega Grande (Big Omega - Ω(·))

●​ Definición: Una función f(n) pertenece a Ω(g(n)) si existen constantes positivas c y


n0 tales que f(n) ≥ c * g(n) para todo n ≥ n0.12
●​ Propósito: Establece una cota inferior asintótica, reflejando el crecimiento
mínimo del tiempo de ejecución en el mejor caso.5
●​ Intuición Práctica: El algoritmo no será mejor que g(n) en su tasa de crecimiento
para entradas grandes.
●​ Ejemplos: 6n³ ∈ Ω(n³) (con c=1, n0=1), 1/3n ∈ Ω(logn) (con c=1/3, n0=1), n! ∈
Ω(2ⁿ).12

3.1.3. Notación Theta Grande (Big Theta - Θ(·))

●​ Definición: Una función f(n) pertenece a Θ(g(n)) si existen constantes positivas c,


d y n0 tales que c * g(n) ≤ f(n) ≤ d * g(n) para todo n ≥ n0.5
●​ Propósito: Se utiliza cuando el tiempo de ejecución crece de la misma manera en
el mejor y en el peor caso, proporcionando una cota ajustada.5
●​ Intuición Práctica: El algoritmo tiene una tasa de crecimiento aproximadamente
igual a g(n) para entradas grandes.
●​ Ejemplos: 6n³ ∈ Θ(n³) (con c=6, d=6, n0=1), 2ⁿ⁺¹ ∈ Θ(2ⁿ), logb n ∈ Θ(loga n)
para cualquier base a, b > 0.12
La notación asintótica también puede emplearse en ecuaciones para simplificar
expresiones y enfocarse en el comportamiento general de la función, ignorando
detalles de menor importancia. Por ejemplo, O(f1(n) + f2(n)) = O(max(f1(n), f2(n))).12
A continuación, se presenta una tabla comparativa de estas notaciones:
Tabla 1: Comparación de Notaciones Asintóticas (O, Ω, Θ)

Notación Símbolo Definición Interpretación Intuición


Formal /Propósito Práctica

O Grande O(g(n)) f(n) ≤ c * g(n) Cota Superior "No es peor


para n ≥ n0 (Peor Caso) que..."

Omega Ω(g(n)) f(n) ≥ c * g(n) Cota Inferior "No es mejor


Grande para n ≥ n0 (Mejor Caso) que..."

Theta Grande Θ(g(n)) c * g(n) ≤ f(n) Cota Ajustada "Es


≤ d * g(n) (Comportami aproximadam
para n ≥ n0 ento Exacto) ente..."

3.2. Órdenes de Complejidad Comunes y su Significado Práctico

Las tasas de crecimiento más bajas en la notación asintótica indican algoritmos más
eficientes, ya que su tiempo de ejecución aumenta más lentamente con el tamaño de la
entrada.5 A continuación, se describen los órdenes de complejidad más comunes y su
significado práctico:
●​ O(1) - Tiempo Constante:
○​ Descripción: El rendimiento del algoritmo no depende de la cantidad de datos
de entrada. Implica un número fijo de operaciones, sin importar el tamaño de
N.11
○​ Ejemplos: Acceder a un elemento en un array por su índice, insertar o eliminar
un nodo en una lista enlazada (si se tiene una referencia al nodo adyacente o
al nodo a eliminar), operaciones de push y pop en una pila, determinar si un
número es par o impar, o la función len() en Python para listas.11
●​ O(log n) - Tiempo Logarítmico:
○​ Descripción: El número de pasos del algoritmo crece muy lentamente con el
tamaño de la entrada. En cada paso, el algoritmo elimina una fracción
significativa de las posibilidades restantes, reduciendo el espacio de
búsqueda.11
○​ Ejemplos: Búsqueda binaria en una lista ordenada, encontrar el número más
grande o más pequeño en un árbol de búsqueda binario, o calcular x elevado a
la potencia N de manera eficiente.11 Para una entrada de mil millones de
elementos, solo se necesitarían aproximadamente 30 operaciones.
●​ O(n) - Tiempo Lineal:
○​ Descripción: El tiempo de ejecución es directamente proporcional a la
cantidad de datos de entrada. El algoritmo típicamente inspecciona cada punto
de datos individualmente una vez.11
○​ Ejemplos: Recorrer todos los elementos de un array o una lista enlazada,
búsqueda lineal de un elemento en una lista, comparar dos cadenas de texto, o
verificar si una cadena es un palíndromo.11
●​ O(n log n) - Tiempo Linealítmico:
○​ Descripción: Este orden de complejidad ofrece una eficiencia intermedia entre
el tiempo lineal y el cuadrático. Es común en algoritmos que emplean la
estrategia de "Divide y Vencerás", donde el problema se divide recursivamente,
y las soluciones de los subproblemas se combinan eficientemente.11
○​ Ejemplos: Algoritmos de ordenación eficientes como Merge Sort, Heap Sort y
Quick Sort (en promedio), o el problema de la Subsecuencia Creciente Más
Larga.15 En la práctica, el tiempo de ejecución de un algoritmo O(N log N)
puede ser comparable al de un algoritmo de tiempo lineal para muchas
aplicaciones.11
●​ O(n^2) - Tiempo Cuadrático:
○​ Descripción: El tiempo de ejecución es proporcional al cuadrado de la
cantidad de datos de entrada. Estos algoritmos escalan mal; si se duplica el
tamaño de los datos, el tiempo de ejecución se cuadruplica.11 A menudo
implican bucles anidados donde cada elemento se compara con cada otro
elemento.
○​ Ejemplos: Algoritmos de ordenación simples como Bubble Sort, Insertion Sort
y Selection Sort, o el recorrido de todos los elementos en un array 2D simple
(matriz cuadrada).11
●​ O(2^n) - Tiempo Exponencial:
○​ Descripción: El crecimiento del tiempo de ejecución se duplica con cada
adición al conjunto de datos de entrada. La curva de crecimiento es
extremadamente pronunciada, comenzando de forma gradual y luego
aumentando de manera meteórica.11
○​ Ejemplos: La implementación recursiva ingenua del cálculo de números de
Fibonacci, o el problema de la Torre de Hanói.15
●​ O(n!) - Tiempo Factorial:
○​ Descripción: Estos algoritmos presentan una tasa de crecimiento
extremadamente rápida, lo que los hace prácticamente inviables para cualquier
tamaño de entrada que no sea muy pequeño.11
○​ Ejemplos: Resolver el problema del viajante de comercio mediante búsqueda
por fuerza bruta (probando todas las permutaciones posibles de ciudades),
generar todas las permutaciones no restringidas de un conjunto parcialmente
ordenado, o encontrar el determinante de una matriz usando la expansión de
Laplace.15
A continuación, se presenta una tabla que resume estos órdenes de complejidad y sus
ejemplos:
Tabla 2: Órdenes de Complejidad Comunes y Ejemplos de Algoritmos

Orden de Nombre Descripción Ejemplos de Implicación


Complejidad del Algoritmos Práctica/Esca
Crecimiento labilidad

O(1) Tiempo No depende Acceso a Ideal;


Constante de N; número array por rendimiento
fijo de índice, óptimo.
operaciones. Push/Pop en
pila, len() en
Python.

O(log n) Tiempo Crece muy Búsqueda Muy eficiente


Logarítmico lentamente Binaria, para grandes
con N; el Búsqueda en N; casi como
problema se Árbol Binario O(1).
reduce de Búsqueda.
significativam
ente en cada
paso.

O(n) Tiempo Lineal Directamente Recorrido de Aceptable;


proporcional array/lista, escala bien
a N; se Búsqueda con N.
procesa cada Lineal,
elemento una Comparación
vez. de cadenas.
O(n log n) Tiempo Eficiencia Merge Sort, Bueno para
Linealítmico intermedia; Heap Sort, ordenar;
común en Quick Sort eficiente para
"Divide y (promedio). grandes N.
Vencerás".

O(n^2) Tiempo Proporcional Bubble Sort, Evitar para


Cuadrático al cuadrado Insertion Sort, grandes N; el
de N; escala Selection rendimiento
mal. Sort, decae
Recorrido de rápidamente.
matriz 2D.

O(2^n) Tiempo Crecimiento Fibonacci Inviable para


Exponencial meteórico; se recursivo N > ~25; solo
duplica con ingenuo, para entradas
cada N Torre de muy
adicional. Hanói. pequeñas.

O(n!) Tiempo Crecimiento Problema del Solo para N


Factorial extremadame Viajante muy
nte rápido; (fuerza bruta), pequeños (N
inviable para Generación < 15); crece
casi cualquier de explosivamen
N. permutacione te.
s.

3.3. Técnicas para el Cálculo de la Complejidad de Algoritmos

El cálculo de la complejidad de un algoritmo se puede abordar mediante diversas


técnicas, dependiendo de su estructura:
●​ Análisis por Estructuras de Control 12:
○​ Secuencia: Si un algoritmo consta de una secuencia de operaciones, la
complejidad total es el máximo de las complejidades de las operaciones
individuales. Por ejemplo, si el proceso P1 tiene complejidad Θ(f1(n)) y P2 tiene
Θ(f2(n)), la complejidad de la secuencia P1 seguido de P2 es Θ(max(f1(n),
f2(n))).
○​ Condicional (IF-ELSE): Para una estructura IF (X) P1 ELSE P2 ENDIF, el
tiempo en el peor caso es el tiempo de la condición tX(n) más el máximo de los
tiempos de las ramas max(tP1(n), tP2(n)).
○​ Bucles (FOR, WHILE, REPEAT):
■​ FOR: Si un bucle FOR se ejecuta m veces y el cuerpo del bucle P(i)
consume una cantidad constante de recursos t (independiente de i o m), la
complejidad total es Θ(m * t). Si el consumo de recursos de P(i) depende
de i o n, se utiliza una sumatoria para calcular la complejidad total.
■​ WHILE/REPEAT: El análisis de estos bucles es más complejo porque el
número de iteraciones no siempre se conoce de antemano. Se pueden
aplicar técnicas como encontrar una función que disminuya en cada
iteración y sea siempre positiva, tratar la iteración como un procedimiento
recursivo, o contar las ejecuciones de una sentencia "barómetro" dentro del
bucle.
●​ Resolución de Relaciones de Recurrencia 10:​

Los algoritmos recursivos, por su naturaleza, se describen de forma natural
mediante relaciones de recurrencia que simulan su flujo de control.10 Resolver
estas relaciones es fundamental para determinar su complejidad.
○​ Método de Sustitución/Iteración: Este método, también conocido como el
"método propuesto" en algunas fuentes, implica expandir la relación de
recurrencia paso a paso de forma reiterada hasta que se observe un patrón
generalizable para cualquier paso K.10 Una vez que se ha generalizado el
comportamiento, se aplica la condición inicial del algoritmo (el caso base no
recursivo) para encontrar una expresión cerrada para la función de
complejidad.10 Este enfoque se considera más intuitivo para los ingenieros, ya
que se alinea directamente con el flujo lógico de la ejecución del algoritmo.10
■​ Ejemplos:
■​ Factorial (t(n) = t(n-1) + 1): Se expande a t(n) = t(n-k) + k. Cuando
n-k=0 (caso base), k=n. Así, t(n) = t(0) + n. Si t(0)=0, la solución es t(n)
= n, lo que implica una complejidad O(n).10
■​ Quick Sort (t(n) = 2t(n/2) + n): Se expande iterativamente: t(n) =
2t(n/2) + n, t(n) = 4t(n/4) + 2n, t(n) = 8t(n/8) + 3n. Generalizando, t(n) =
2^k t(n/2^k) + kn. Cuando n/2^k = 1, k = log₂n. Sustituyendo, t(n) = n t(1)
+ n log₂n. Si t(1)=0, la solución es t(n) = n log₂n, con una complejidad
O(n log n).10
■​ Búsqueda Binaria (t(n) = t(n/2) + 1): Se expande a t(n) = t(n/2^k) + k.
Cuando n/2^k = 1, k = log₂n. Si t(1)=1, la solución es t(n) = 1 + log₂n,
con una complejidad O(log n).10
○​ Método del Teorema Maestro: Este teorema es aplicable a recurrencias de la
forma T(n) = aT(n/b) + f(n), donde a ≥ 1 y b > 1 son constantes. Proporciona
soluciones directas basadas en la comparación de la función f(n) con n^(logb a)
en tres casos distintos.12 Es una herramienta poderosa para el análisis de
algoritmos de "divide y vencerás".
○​ Método de la Ecuación Característica: Se utiliza para resolver ciertas
recurrencias lineales con coeficientes constantes, como T(n) = a1T(n-1) +
a2T(n-2) +... + akT(n-k) + b^n * p(n).12 Este método implica encontrar las raíces
de una ecuación característica asociada a la recurrencia y construir la solución
general a partir de ellas. Un ejemplo clásico es el cálculo de la secuencia de
Fibonacci.10
○​ Cambio de Variable: Esta técnica se emplea cuando las recurrencias no
pueden resolverse directamente con el Teorema Maestro o el método de la
Ecuación Característica. Consiste en definir una nueva variable para
transformar la recurrencia original en una forma que sí pueda ser resuelta por
otros métodos.12
La existencia de múltiples métodos para resolver relaciones de recurrencia pone de
manifiesto una tensión entre la elegancia matemática y la intuición práctica en el
análisis de algoritmos. Los métodos más formales, como el Teorema Maestro o la
Ecuación Característica, son herramientas matemáticas generalizadas y potentes que
ofrecen soluciones concisas, pero a veces pueden oscurecer el proceso algorítmico
subyacente para quienes se inician en el campo. Por otro lado, el método iterativo,
aunque quizás menos formal para casos muy complejos, refleja directamente la
ejecución paso a paso de un algoritmo recursivo. Esta diversidad de enfoques atiende
a diferentes estilos de aprendizaje y contextos de aplicación. Para un análisis rápido y
de alto nivel de un algoritmo estándar de "divide y vencerás", el Teorema Maestro es
invaluable. Sin embargo, para comprender el camino de ejecución detallado de una
función recursiva específica, la sustitución iterativa puede ser más esclarecedora. Esto
subraya que el análisis de algoritmos, aunque arraigado en las matemáticas, es
también una disciplina aplicada, y la elección de la técnica de análisis puede depender
de la audiencia, el nivel de detalle deseado y los conocimientos específicos que se
busquen.

4. Clases de Problemas en Complejidad Computacional

La teoría de la complejidad computacional clasifica los problemas en función de la


cantidad de recursos que un algoritmo necesita para resolverlos. Esta clasificación
ayuda a comprender la dificultad inherente de los problemas, independientemente de la
eficiencia de un algoritmo particular.

4.1. Clase P: Problemas Resolubles en Tiempo Polinomial

La clase P (de "Polinomial") abarca todos los problemas de decisión que pueden ser
resueltos por una máquina de Turing determinista en tiempo polinomial.16 Esto significa
que existe un algoritmo capaz de encontrar la solución en un número de pasos acotado
por una función polinomial del tamaño de la entrada, es decir,
O(n^k) para algún entero k ≥ 0.16
Desde una perspectiva práctica, los problemas en la clase P se consideran
"computacionalmente tratables" o "eficientemente resolubles".16 Esto se debe a que,
para tamaños de entrada razonables, los algoritmos de tiempo polinomial son lo
suficientemente rápidos para ser útiles. Una propiedad importante de los algoritmos de
tiempo polinomial es que son "cerrados respecto a la composición".19 Esto implica que
si se combinan varias funciones, cada una con un tiempo de ejecución polinomial, el
algoritmo completo resultante también tendrá un tiempo de ejecución polinomial.
Ejemplos típicos de problemas en la clase P incluyen:
●​ La clasificación de una lista de números (por ejemplo, mediante Merge Sort o
Quick Sort).16
●​ Encontrar el camino mínimo entre dos vértices en un grafo.19
●​ Determinar si un grafo es conexo.18
●​ Verificar si existen números repetidos en una lista.18

4.2. Clase NP: Problemas Verificables en Tiempo Polinomial (No Determinista)

La clase NP (que significa "Tiempo Polinomial No Determinista") comprende problemas


de decisión para los cuales, si se proporciona una solución propuesta, esta puede ser
verificada en tiempo polinomial.16 En otras palabras, si la respuesta a un problema NP
es "sí", debe existir un "objeto testigo" o "certificado" que demuestre esa respuesta, y
un algoritmo verificador que pueda comprobar la corrección de este testigo en un
tiempo polinomial, aunque encontrar la solución en sí misma puede ser
computacionalmente difícil.16
Conceptos clave asociados a la clase NP son:
●​ Problema de Decisión: Un problema que tiene una respuesta binaria, es decir,
"sí" o "no".20
●​ Máquina de Turing No Determinista: Un modelo computacional abstracto que
puede "adivinar" una posible solución y luego verificar su validez en tiempo
polinomial.19
●​ Objeto Testigo (Witness): Una prueba o certificado que acompaña a una
respuesta "sí" y que el algoritmo verificador puede comprobar eficientemente.18
La relación entre P y NP es fundamental: la clase P es un subconjunto de NP.18 Esto
significa que cualquier problema que pueda resolverse eficientemente (en P) también
puede verificarse eficientemente (en NP). Sin embargo, la cuestión central y uno de los
problemas sin resolver más importantes en la ciencia de la computación es si P es un
subconjunto
estricto de NP, es decir, si P = NP.16
Ejemplos de problemas en NP incluyen:
●​ Problema de la Suma de Subconjuntos: Dado un conjunto de números,
determinar si existe un subconjunto cuya suma sea un valor dado. El testigo sería
el subconjunto, y su suma se puede verificar en tiempo lineal.18
●​ Problema del Camino Hamiltoniano: Dado un grafo, determinar si existe un
camino que visite cada vértice exactamente una vez. El testigo es el orden de los
vértices en el camino, y su validez se puede verificar en tiempo polinomial.18
●​ Problema 3-SAT: Dada una expresión booleana en forma normal conjuntiva con
cláusulas de tres literales, determinar si existe una asignación de verdad a las
variables que haga la expresión verdadera. El testigo es una asignación de verdad,
cuya validez se verifica en tiempo polinomial.18
Para estos problemas, las soluciones ingenuas (fuerza bruta) suelen tener una
complejidad exponencial, y hasta la fecha no se conocen algoritmos de tiempo
polinomial para resolverlos.18

4.3. Clase NP-Completo: Los Problemas Más Difíciles en NP

La clase NP-Completo (NP-C) es un subconjunto crucial de los problemas de decisión


dentro de NP.18 Un problema se considera NP-Completo si cumple dos condiciones:
1.​ Pertenece a la clase NP.
2.​ Todo problema en NP puede reducirse polinomialmente a él.18
Una reducción polinomial implica una transformación algorítmica de una instancia de
un problema A a una instancia de un problema B, tal que la respuesta de A es "sí" si y
solo si la respuesta de B es "sí", y esta transformación se realiza en tiempo
polinomial.18 La importancia de esta reducción radica en que, si un problema B es
NP-Completo y se encontrara un algoritmo de tiempo polinomial para resolverlo,
entonces, por la propiedad de reducción,
todos los problemas en NP podrían resolverse en tiempo polinomial. Esto implicaría
que P = NP.18
La historia de esta clase es significativa: el problema SAT (Satisfacibilidad Booleana)
fue el primero en ser demostrado como NP-Completo por Stephen Cook y Leonid
Levin. Posteriormente, Richard Karp identificó 21 problemas adicionales de gran interés
computacional que también son NP-Completo.18
Ejemplos prominentes de problemas NP-Completo incluyen:
●​ El Problema del Viajante de Comercio (en su versión de decisión).16
●​ El Problema de la Suma de Subconjuntos.18
●​ El Problema 3-SAT.18
●​ El Problema del Número de Clique de un grafo.18
●​ El Problema del Número Cromático de un grafo.18

4.4. Clase NP-Duro: Problemas al Menos Tan Difíciles como los NP-Completos

La clase NP-Duro (NP-hard) es el conjunto de problemas de decisión H tales que


cualquier problema L en NP puede ser transformado polinomialmente en H.18
La distinción fundamental entre NP-Completo y NP-Duro radica en que un problema
NP-Duro no necesita estar en NP.24 Esto significa que un problema NP-Duro puede ser
incluso más difícil que los problemas en NP, o incluso ser un problema indecidible (es
decir, no existe ningún algoritmo que pueda resolverlo en un tiempo finito para todas las
entradas posibles).24
La implicación es que si se pudiera resolver un problema NP-Duro en tiempo
polinomial, entonces todos los problemas en NP también podrían resolverse en tiempo
polinomial.18 Sin embargo, lo contrario no es necesariamente cierto; resolver un
problema NP-Completo no garantiza la solución de un problema NP-Duro en tiempo
polinomial, ya que este último podría pertenecer a una clase de complejidad superior.24
Ejemplos de problemas NP-Duro incluyen:
●​ El Problema del Viajante de Comercio en su versión de optimización (encontrar la
ruta más corta, no solo decidir si existe una ruta menor que un cierto costo).18
●​ El problema de determinar si una máquina de Turing acepta una entrada, que es
un problema indecidible pero se clasifica como NP-Duro.24

4.5. El Problema P vs. NP: Un Desafío Abierto en la Ciencia de la Computación

La relación entre las clases P y NP es una de las cuestiones más profundas y sin
resolver en la teoría de la complejidad computacional.16 La pregunta fundamental es:
"¿Será que P = NP?".18 Esta interrogante se traduce en si todos los problemas para los
que una solución puede ser verificada eficientemente en tiempo polinomial también
pueden ser resueltos (encontrada su solución) eficientemente en tiempo polinomial.16
A pesar de décadas de intensos esfuerzos por parte de matemáticos y científicos de la
computación, no se ha encontrado un algoritmo de tiempo polinomial para ninguno de
los problemas NP-Completo, ni se ha logrado probar que tal algoritmo sea imposible.18
El problema P vs. NP es un dilema fundamental que moldea los límites de la
computación y la innovación. Su resolución redefiniría nuestra comprensión de qué
problemas pueden ser resueltos eficientemente por las computadoras. Si se
demostrara que P = NP, implicaría que para cada problema donde una solución puede
ser rápidamente verificada, una solución también puede ser rápidamente encontrada.
Esto tendría implicaciones revolucionarias en campos tan diversos como la criptografía
(potencialmente permitiendo descifrar esquemas de encriptación actuales), el
descubrimiento de fármacos (facilitando la identificación de estructuras moleculares
óptimas), la logística (permitiendo la planificación de rutas perfectas para entregas) y la
inteligencia artificial (resolviendo problemas de optimización complejos con una
eficiencia sin precedentes).18 En esencia, significaría que "resolver problemas sería
equivalente a verificar sus soluciones".18
Por otro lado, si se demostrara que P ≠ NP, se confirmaría que ciertos problemas son
inherentemente difíciles de resolver eficientemente, sin importar los avances futuros en
hardware. Esto validaría los fundamentos de la criptografía moderna, que a menudo se
basa en la supuesta dificultad de problemas NP (como la factorización de números
grandes para la encriptación de clave pública). También dirigiría la investigación hacia
algoritmos de aproximación o heurísticas para problemas NP-Duro, reconociendo su
intratabilidad inherente.
El problema P vs. NP no es solo un rompecabezas teórico; es una fuerza impulsora
para la investigación en algoritmos, teoría de la complejidad y aplicaciones prácticas. El
Clay Mathematics Institute ofrece un premio de un millón de dólares por su resolución,
lo que subraya sus profundas implicaciones tanto para las matemáticas puras como
para el futuro de la tecnología. Nos obliga a enfrentar los límites últimos de lo que es
computacionalmente posible.
A continuación, se presenta una tabla que resume las clases de complejidad
computacional:
Tabla 3: Clases de Complejidad Computacional (P, NP, NP-Completo, NP-Duro)

Clase Definición Significado Relación con Ejemplos


Clave Práctico otras Clases Típicos

P Resoluble en Tratables/Efici P ⊆ NP Ordenamient


tiempo entes. o, Búsqueda
polinomial. Binaria,
Camino
Mínimo.
NP Verificable en Verificación P ⊆ NP Suma de
tiempo Rápida; Subconjuntos
polinomial. Solución , Camino
Lenta Hamiltoniano,
(posiblemente 3-SAT.
).

NP-Completo En NP; todo Los "más NP-Completo Problema del


problema en difíciles" en ⊆ NP; Viajante
NP se reduce NP; su NP-Completo (decisión),
a él solución P ⊆ NP-Duro 3-SAT.
polinomialme implicaría
nte. P=NP.

NP-Duro Todo Al menos tan NP-Completo Problema del


problema en difíciles como ⊆ NP-Duro Viajante
NP se reduce NP-Completo; (optimización)
a él pueden ser , Problema de
polinomialme indecidibles. la Parada.
nte; no
necesariamen
te en NP.

Conclusión

El análisis de algoritmos es una disciplina fundamental que trasciende la mera


codificación para adentrarse en la lógica subyacente de la resolución de problemas. Es
esencial para diseñar software eficiente y escalable, enfocándose en la optimización de
los recursos computacionales, principalmente el tiempo de procesamiento y el espacio
de memoria. Las medidas asintóticas, como las notaciones O, Ω y Θ, proporcionan un
lenguaje universal e independiente del hardware para predecir el comportamiento de
los algoritmos a gran escala, permitiendo una evaluación objetiva de su eficiencia. Las
relaciones de recurrencia, por su parte, son herramientas cruciales para analizar el
rendimiento de los algoritmos recursivos.
Los órdenes de complejidad y las clases de problemas computacionales (P, NP,
NP-Completo y NP-Duro) clasifican los desafíos según su dificultad inherente, desde
los problemas eficientemente resolubles hasta aquellos cuya solución eficiente sigue
siendo un misterio. El problema P vs. NP, en particular, se erige como el desafío central
que define los límites de lo que es computacionalmente posible de manera eficiente.
A pesar de los avances exponenciales en el hardware, la relevancia del análisis
algorítmico no ha disminuido; de hecho, se ha intensificado. La paradoja reside en que,
aunque los ordenadores son cada vez más rápidos, la complejidad temporal sigue
siendo crucial porque el volumen de datos y la complejidad de los problemas a menudo
superan el ritmo de las mejoras de hardware.7 Un algoritmo ineficiente puede llevar a
un rendimiento catastrófico incluso en el hardware más avanzado.11 La escala de los
datos y la sofisticación de los problemas, como los que se encuentran en el Big Data y
los modelos de Inteligencia Artificial, crecen a un ritmo que las mejoras de hardware
por sí solas no pueden compensar. Esto convierte la eficiencia algorítmica en un cuello
de botella constante. Incluso mejoras marginales en la eficiencia de un algoritmo,
cuando se aplican a escalas masivas, se traducen en ahorros inmensos de recursos
computacionales (energía, tiempo de procesamiento, memoria) y mejoras significativas
en la experiencia del usuario.7 Este fenómeno genera un ciclo de retroalimentación
continua: a medida que el hardware mejora, permite abordar problemas más grandes y
complejos, lo que a su vez exige algoritmos aún más eficientes. El análisis algorítmico,
lejos de ser un campo estático, es una disciplina dinámica y cada vez más crítica, que
asegura que el progreso computacional siga siendo viable y sostenible en una era de
datos en constante expansión.
Los algoritmos son el "combustible" de la nueva revolución industrial, impulsando la
Ciencia de Datos, el Machine Learning y la Inteligencia Artificial.2 El análisis algorítmico
permite a las empresas procesar rápidamente grandes volúmenes de información,
reducir errores y tomar decisiones estratégicas en tiempo real, impactando
directamente su competitividad.3
De cara al futuro, la investigación en complejidad computacional seguirá siendo un
motor clave para la innovación. La búsqueda de algoritmos más eficientes y la
comprensión de los límites computacionales son áreas activas y fructíferas. El
problema P vs. NP, en particular, continúa incentivando el desarrollo de nuevas
técnicas de optimización y algoritmos aproximados para problemas que actualmente se
consideran intratables. La creciente complejidad de los sistemas de IA y Big Data exige
un análisis algorítmico aún más sofisticado para garantizar su escalabilidad,
sostenibilidad y eficiencia energética, consolidando el análisis de algoritmos como una
piedra angular indispensable de la informática.
Fuentes citadas
1.​ ¿Para qué sirve un algoritmo en informática? - Universidad Isabel I, acceso: junio
29, 2025, [Link]
2.​ Algoritmo : Definición y usos - DataScientest, acceso: junio 29, 2025,
[Link]
3.​ Los algoritmos determinan la competitividad de la empresa - Telefónica Tech,
acceso: junio 29, 2025,
[Link]
4.​ Aprendizaje automático - 10 algoritmos importantes y su aplicación - Konfuzio,
acceso: junio 29, 2025,
[Link]
5.​ Complejidad Computacional y Análisis de Algoritmos | Algor Cards, acceso: junio
29, 2025,
[Link]
l-algoritmos
6.​ Algoritmos y Complejidad: Conceptos, Ejemplos | StudySmarter, acceso: junio 29,
2025,
[Link]
itmos-y-complejidad/
7.​ Análisis de algoritmos: Eficiencia, Métodos - StudySmarter ES, acceso: junio 29,
2025,
[Link]
-ciencias-de-la-computacion/analisis-de-algoritmos/
8.​ ajimenezrosa/ANALISIS-Y-DISE-O-DE-ALGORITMOS - GitHub, acceso: junio 29,
2025, [Link]
9.​ Algoritmos: qué son y qué tipos existen - Ferrovial, acceso: junio 29, 2025,
[Link]
10.​Técnica para solución de recurrencias, usada en el análisis de la ..., acceso: junio
29, 2025,
[Link]
00008
11.​Notación Big O y Guía de Complejidad Temporal: Intuición y ..., acceso: junio 29,
2025, [Link]
12.​Algoritmos y Complejidad - Técnicas y Herramientas, acceso: junio 29, 2025,
[Link]
[Link]
13.​Nivel Superior TÉCNICAS DE ANÁLISIS DE ALGORITMOS, acceso: junio 29,
2025,
[Link]
pdf
14.​Notación asintótica (artículo) | Algoritmos | Khan Academy, acceso: junio 29,
2025,
[Link]
otation/a/asymptotic-notation
15.​time complexity - Examples of Algorithms which has O(1), O(n log n ..., acceso:
junio 29, 2025,
[Link]
1-on-log-n-and-olog-n-complexities
16.​¿Cuál es la diferencia entre las clases P y NP en la teoría de la complejidad
computacional y cómo se relacionan con los conceptos de decidir y verificar la
pertenencia en los lenguajes? - Academia EITCA, acceso: junio 29, 2025,
[Link]
r%C3%ADa-de-la-complejidad-computacional-cctf/complejidad/definici%C3%B3n-
de-np-y-verificabilidad-polinomial/examen-revisi%C3%B3n-definici%C3%B3n-de-
np-y-verificabilidad-polinomial/%C2%BFCu%C3%A1l-es-la-diferencia-entre-las-cl
ases-p-y-np-en-la-teor%C3%ADa-de-la-complejidad-computacional-y-c%C3%B3
mo-se-relacionan-con-los-conceptos-de-decidir-y-verificar-la-membres%C3%ADa
-en-los-lenguajes%3F/
17.​[Link], acceso: junio 29, 2025,
[Link]
de%20complejidad%20P,-Todo%20lo%20que&text=La%20clase%20de%20compl
ejidad%20consiste,tiempo%20O%20(%20n%20k%20)%20.
18.​Clases de complejidad y P vs. NP — Matemáticas Discretas para ..., acceso: junio
29, 2025, [Link]
19.​Clases de complejidad P y NP - Wikipedia, la enciclopedia libre, acceso: junio 29,
2025, [Link]
20.​¿Cuál es la definición de la clase NP en el contexto de la teoría de la complejidad
computacional? - Academia EITCA, acceso: junio 29, 2025,
[Link]
r%C3%ADa-de-la-complejidad-computacional-cctf/complejidad/prueba-de-que-sat
-es-np-completo/examen-revisi%C3%B3n-prueba-de-que-sat-es-np-completo/%C
2%BFCu%C3%A1l-es-la-definici%C3%B3n-de-la-clase-np-en-el-contexto-de-la-te
or%C3%ADa-de-la-complejidad-computacional%3F/
21.​P 'vs' NP, el dilema matemático que creó la complejidad computacional, acceso:
junio 29, 2025,
[Link]
plejidad-computacional/
22.​Untitled - UTM, acceso: junio 29, 2025, [Link]
23.​[Link], acceso: junio 29, 2025,
[Link]
%20complejidad,ser%20transformado%20polinomialmente%20en%20H.
24.​¿Qué CHUTA es un Problema NP-Difícil? : r/computerscience - Reddit, acceso:
junio 29, 2025,
[Link]
_nphard_problem/?tl=es-419

También podría gustarte