Notación Big-O desde cero
Comprenda por qué importa el crecimiento asintótico, cómo eliminar constantes y términos de orden inferior, y cómo interpretar Big-O de un vistazo.
Notación Big-O desde cero es una lección gratuita de DSA Interview Prep en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de DSA Interview Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de DSA Interview Prep incluye 4 lecciones en total.
¿Por qué medir la eficiencia de los algoritmos?
Dos programas pueden ser correctos y, aun así, uno terminar en un instante mientras el otro tarde horas. La complejidad temporal describe cómo crece el tiempo de ejecución a medida que aumenta la entrada.
# O(n) approach
def find_max_linear(nums):
m = nums[0]
for n in nums:
if n > m: m = n
return m
# O(n^2) approach (unnecessary double loop)
def find_max_quadratic(nums):
for i in range(len(nums)):
is_max = all(nums[i] >= nums[j] for j in range(len(nums)))
if is_max: return nums[i]
print(find_max_linear([3, 1, 4, 1, 5, 9])) # 9Big-O: cota superior asintótica
Big-O describe la cota superior del peor caso sobre el crecimiento del coste. El truco consiste en eliminar las constantes y los términos menores, porque a gran escala solo importa el término dominante. Consulte el código.
# T(n) = 3n^2 + 5n + 100 is O(n^2)
# because the n^2 term dominates for large n
# T(n) = 2n + 1000 is O(n)
# the constant 1000 becomes negligible
# Rule: drop constants and lower-order terms
# 5n^3 + 2n^2 + n + 1 => O(n^3)
# 100 * log(n) + n => O(n)
print('O(n^2) example: counting iterations')
n = 1000
count = sum(1 for i in range(n) for j in range(n))
print(count) # 1_000_000 = n^2Clases habituales de complejidad
De más rápida a más lenta: O(1), O(log n), O(n), O(n log n), O(n^2), O(2^n), O(n!). Conocerlas le permite elegir el enfoque adecuado antes de escribir una sola línea.
import math
n = 1000
print(f'O(1): {1}')
print(f'O(log n): {int(math.log2(n))}')
print(f'O(n): {n}')
print(f'O(n log n): {int(n * math.log2(n))}')
print(f'O(n^2): {n**2}')
# O(2^n) for n=1000 is astronomically large
# O(n!) even largerEliminar constantes: por qué importa
Ejecutar 5n pasos o 2n pasos es O(n): las constantes dependen del hardware, no del algoritmo. Big-O las omite para que pueda comparar el crecimiento en igualdad de condiciones.
# Both are O(n) — different constants
def count_a(n):
total = 0
for i in range(n): # n ops
total += 1
for i in range(n): # n ops
total += 1
return total # T(n) = 2n => O(n)
def count_b(n):
total = 0
for i in range(5 * n): # 5n ops
total += 1
return total # T(n) = 5n => O(n)
print(count_a(10), count_b(10)) # 20 50Mejores, promedio y peores casos
Big-O representa el peor caso; Omega, el mejor caso; y Theta, un límite ajustado para ambos. Cuando en una entrevista le preguntan por «la complejidad», casi siempre se refieren al peor caso.
def linear_search(nums, target):
for i, n in enumerate(nums):
if n == target:
return i # best case: target at index 0 => O(1)
return -1 # worst case: not found => O(n)
# Best case O(1): target is first element
print(linear_search([5,1,2,3], 5)) # 0
# Worst case O(n): target not in list
print(linear_search([1,2,3,4], 9)) # -1O(log n): reducir a la mitad el espacio de búsqueda
Un algoritmo es O(log n) cuando reduce la entrada a la mitad en cada paso, como ocurre con la búsqueda binaria. Incluso para mil millones de elementos, solo requiere unos 30 pasos: es increíblemente rápido. Consulte el código.
def binary_search(arr, target):
lo, hi = 0, len(arr) - 1
steps = 0
while lo <= hi:
steps += 1
mid = (lo + hi) // 2
if arr[mid] == target:
return mid, steps
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1, steps
import math
arr = list(range(1000))
idx, s = binary_search(arr, 999)
print(f'Found at {idx} in {s} steps (log2(1000)~={math.log2(1000):.1f})')O(n log n): límite inferior de la ordenación
Cualquier algoritmo de ordenación por comparación necesita al menos O(n log n) en el peor caso: es un límite inferior matemático real. Por eso, ordenar y luego recorrer tiene una complejidad total de O(n log n), no de O(n^2). El código muestra merge sort.
# Merge sort: O(n log n)
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(a, b):
res, i, j = [], 0, 0
while i < len(a) and j < len(b):
if a[i] <= b[j]: res.append(a[i]); i+=1
else: res.append(b[j]); j+=1
return res + a[i:] + b[j:]
print(merge_sort([5,2,8,1,9,3])) # [1,2,3,5,8,9]Complejidad amortizada
El análisis amortizado promedia el coste de muchas operaciones. El método append de Python tiene un coste amortizado de O(1): normalmente es instantáneo, y el coste excepcional de O(n) al redimensionar se distribuye entre todas las operaciones append.
# Dynamic array append is O(1) amortised
import sys
lst = []
capacities = []
for i in range(16):
lst.append(i)
capacities.append(sys.getsizeof(lst))
# Size jumps show reallocation events
for i, c in enumerate(capacities):
if i > 0 and capacities[i] != capacities[i-1]:
print(f'Realloc at i={i}, new size={c} bytes')Reconocer la complejidad en el código
Una regla rápida: cuente los bucles. Un bucle es O(n), dos bucles anidados son O(n^2) y un bucle que reduce el rango a la mitad es O(log n). Los recorridos independientes se suman; solo los bucles anidados se multiplican. Consulte el código.
# Two independent passes: O(n) + O(n) = O(n)
def two_passes(nums):
total = sum(nums) # O(n)
mean = total / len(nums)
diffs = [abs(n - mean) for n in nums] # O(n)
return max(diffs) # O(n)
# Overall: O(n) -- NOT O(n^2)
# Nested loops: O(n) * O(n) = O(n^2)
def all_pairs(nums):
pairs = []
for i in range(len(nums)): # O(n)
for j in range(i+1, len(nums)): # O(n)
pairs.append((nums[i], nums[j]))
return pairs # O(n^2)Conceptos básicos de complejidad espacial
La complejidad espacial mide la memoria adicional que utiliza, aparte de la entrada. Invertir una estructura in situ es O(1); utilizar un mapa hash es O(n). Cuando intercambie tiempo por espacio, indique siempre ambos.
# O(1) space: reverse in-place
def reverse_inplace(arr):
l, r = 0, len(arr) - 1
while l < r:
arr[l], arr[r] = arr[r], arr[l]
l += 1; r -= 1
# O(n) space: create reversed copy
def reverse_copy(arr):
return arr[::-1]
a = [1, 2, 3, 4, 5]
reverse_inplace(a)
print(a) # [5, 4, 3, 2, 1]Hablar de complejidad en entrevistas
Indique siempre la complejidad sin esperar a que se la pregunten: «Esto requiere O(n log n) de tiempo y O(n) de espacio». Después, proponga una opción más rápida. Este hábito demuestra una verdadera experiencia profesional.
# Example of explaining complexity step by step
def two_sum(nums, target):
# O(n) time: one pass through nums
# O(n) space: hash map stores up to n elements
seen = {} # value -> index
for i, n in enumerate(nums):
complement = target - n
if complement in seen: # O(1) lookup
return [seen[complement], i]
seen[n] = i
return []
print(two_sum([2, 7, 11, 15], 9)) # [0, 1]Comprobación rápida
Comprobación rápida: demuestre cuánto ha asimilado sobre Big-O y las clases de complejidad. Solo es una pregunta; puede hacerlo. 🎯
Resumen de la lección
Resumen: Big-O representa el crecimiento en el peor caso omitiendo las constantes; ya conoce las clases desde O(1) hasta O(n!), y sabe que los bucles independientes se suman mientras que los anidados se multiplican.
Aprende Python con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 30
- Lecciones
- 120
Preguntas frecuentes
¿La lección «Notación Big-O desde cero» es gratis?
Sí — el texto completo de «Notación Big-O desde cero» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de DSA Interview Prep, actualiza a CoddyKit PRO. El curso de DSA Interview Prep incluye 4 lecciones en total.
¿Qué aprenderé en «Notación Big-O desde cero»?
Comprenda por qué importa el crecimiento asintótico, cómo eliminar constantes y términos de orden inferior, y cómo interpretar Big-O de un vistazo. Practicas DSA Interview Prep con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar DSA Interview Prep?
No se requiere experiencia previa. DSA Interview Prep en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Notación Big-O desde cero»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de DSA Interview Prep?
Sí. Cada lección de DSA Interview Prep incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Notación Big-O desde cero
- Análisis de bucles y bucles anidados
- Recursión y método del árbol de recursión
- Complejidad espacial y compensaciones