DSA Interview Prep · Lección

Complejidad espacial y compensaciones

Mida el espacio auxiliar de las pilas de llamadas y las estructuras de datos auxiliares, y reconozca las compensaciones entre tiempo y espacio en la memoización y los algoritmos in-place.

Lección 4 de 413 pasos

Complejidad espacial y compensaciones es una lección gratuita de DSA Interview Prep en CoddyKit. Esta es la lección 4 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.

¿Qué mide la complejidad espacial?

La complejidad espacial mide la memoria adicional más allá de la entrada, denominada espacio auxiliar. Unas pocas variables requieren O(1); un array de resultados o un mapa hash requieren O(n). Consulte el código.

# O(1) auxiliary space
def sum_array(nums):
    total = 0       # one integer variable
    for n in nums:
        total += n  # constant extra space
    return total

# O(n) auxiliary space
def copy_array(nums):
    return list(nums)  # allocates n slots

print(sum_array([1, 2, 3, 4]))  # 10
print(copy_array([1, 2, 3, 4]))  # [1, 2, 3, 4]

Espacio de la pila de llamadas en la recursión

Cada llamada recursiva añade un marco de pila, por lo que la profundidad determina el espacio utilizado. La recursión lineal es O(n); el recorrido DFS de un árbol equilibrado es O(log n). Una versión iterativa puede controlarlo mejor.

import sys

def recursive_sum(n):
    if n == 0: return 0
    return n + recursive_sum(n - 1)
# Space: O(n) stack frames

def iterative_sum(n):
    total = 0
    while n > 0:
        total += n
        n -= 1
    return total
# Space: O(1)

print(recursive_sum(100))   # 5050
print(iterative_sum(100))   # 5050

Espacio de merge sort: O(n)

Merge sort necesita un espacio adicional O(n) para sus arrays temporales. Ese es el coste de una ordenación estable O(n log n); heap sort ahorra espacio, pero no es estable. Consulte el código.

import tracemalloc

tracemalloc.start()

def merge_sort(arr):
    if len(arr) <= 1: return arr
    m = len(arr) // 2
    l = merge_sort(arr[:m])    # new list
    r = merge_sort(arr[m:])    # new list
    out, i, j = [], 0, 0
    while i < len(l) and j < len(r):
        if l[i] <= r[j]: out.append(l[i]); i+=1
        else:             out.append(r[j]); j+=1
    return out + l[i:] + r[j:]

data = list(range(1000, 0, -1))
merge_sort(data)
_, peak = tracemalloc.get_traced_memory()
print(f'Peak memory: {peak} bytes')  # proportional to n

Algoritmos in situ: espacio O(1)

Un algoritmo in situ modifica directamente la entrada sin almacenamiento adicional proporcional, como al invertir un array con dos punteros. Así, el espacio utilizado se mantiene en O(1). Consulte el código.

def reverse_inplace(arr):
    l, r = 0, len(arr) - 1
    while l < r:
        arr[l], arr[r] = arr[r], arr[l]  # swap
        l += 1
        r -= 1
    # Space: O(1) -- only two pointer variables

def rotate_right(arr, k):
    '''Rotate array right by k positions in-place.'''
    n = len(arr)
    k %= n
    arr.reverse()          # O(1) space
    arr[:k] = arr[:k][::-1]
    arr[k:]  = arr[k:][::-1]

a = [1, 2, 3, 4, 5]
rotate_right(a, 2)
print(a)  # [4, 5, 1, 2, 3]

Equilibrio entre tiempo y espacio: Two-Sum

El equilibrio entre tiempo y espacio aparece en todas partes. Two-Sum requiere O(n^2) de tiempo y O(1) de espacio, o bien O(n) de tiempo y O(n) de espacio mediante un mapa hash. Mencione ambas opciones y pregunte qué factor es más importante.

# O(n^2) time, O(1) space
def two_sum_slow(nums, target):
    for i in range(len(nums)):          # O(n)
        for j in range(i+1, len(nums)): # O(n)
            if nums[i] + nums[j] == target:
                return [i, j]
    return []

# O(n) time, O(n) space
def two_sum_fast(nums, target):
    seen = {}                    # O(n) space
    for i, n in enumerate(nums):
        comp = target - n
        if comp in seen:         # O(1) lookup
            return [seen[comp], i]
        seen[n] = i
    return []

print(two_sum_fast([2, 7, 11, 15], 9))  # [0, 1]

Espacio de memoización frente a tabulación

La memoización de arriba abajo cuesta O(n) por la memoización más O(n) por la pila; la tabulación de abajo arriba evita la pila. Conservar solo las últimas filas reduce el espacio a O(1): programación dinámica optimizada en espacio.

# Fibonacci: O(n) space with full table
def fib_table(n):
    dp = [0] * (n + 1)
    dp[1] = 1
    for i in range(2, n + 1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

# O(1) space: keep only last two values
def fib_optimal(n):
    if n <= 1: return n
    a, b = 0, 1
    for _ in range(2, n + 1):
        a, b = b, a + b
    return b

print(fib_table(10))    # 55
print(fib_optimal(10))  # 55

Espacio de un mapa hash: O(n)

Un mapa hash suele ser el coste espacial O(n) de las soluciones: un conjunto de elementos vistos para los visitados o un mapa de frecuencias para contar. Indíquelo siempre: «O(n) de tiempo y O(n) de espacio» es la respuesta completa.

def contains_duplicate(nums):
    # O(n) time, O(n) space
    seen = set()
    for n in nums:
        if n in seen: return True
        seen.add(n)
    return False

def group_anagrams(words):
    # O(n*m) time, O(n) space  (m = avg word length)
    from collections import defaultdict
    groups = defaultdict(list)
    for w in words:
        groups[tuple(sorted(w))].append(w)
    return list(groups.values())

print(contains_duplicate([1,2,3,1]))  # True
print(group_anagrams(['eat','tea','tan','ate','nat','bat']))

Análisis espacial de algoritmos de grafos

Los grafos requieren un espacio considerable: una lista de adyacencia ocupa O(V + E), el conjunto de visitados y la cola de BFS ocupan O(V), y la recursión de DFS puede alcanzar una profundidad O(V). Exprese el espacio de los grafos en función de V y E.

from collections import deque

def bfs(graph, start):
    # Space: O(V) for visited set + O(V) for queue
    visited = set()      # O(V)
    queue = deque([start])  # O(V) max
    order = []
    while queue:
        node = queue.popleft()
        if node in visited: continue
        visited.add(node)
        order.append(node)
        for nb in graph.get(node, []):
            queue.append(nb)
    return order

g = {0:[1,2], 1:[3], 2:[3], 3:[]}
print(bfs(g, 0))  # [0, 1, 2, 3]

Problemas de asignación en cadenas y arrays

Las asignaciones ocultas pueden introducir un espacio O(n): el slicing crea una lista nueva, y usar + con cadenas dentro de un bucle es O(n^2). sorted() crea una copia, pero lst.sort() modifica la estructura in situ. Consulte el código.

# Hidden allocations:
nums = [1, 2, 3, 4, 5]

# Creates a NEW list -- O(n) space
slice_copy = nums[1:4]  # [2, 3, 4]

# Creates a NEW sorted list -- O(n) space
sorted_copy = sorted(nums)  # nums unchanged

# Sorts IN PLACE -- O(1) extra space
nums.sort()

print(slice_copy)   # [2, 3, 4]
print(sorted_copy)  # [1, 2, 3, 4, 5]
print(nums)         # [1, 2, 3, 4, 5]

Reconocer los equilibrios espaciales en entrevistas

Indique de antemano la complejidad espacial. Si la persona entrevistadora quiere reducirla, algunas opciones habituales son utilizar programación dinámica de abajo arriba en lugar de memoización, o una ordenación in situ en lugar de un mapa hash. Consulte el código.

# Problem: find if array has duplicates
# Option 1: O(1) time-per-check, O(n) space
def has_dup_hash(nums):
    return len(nums) != len(set(nums))

# Option 2: O(n log n) time, O(1) extra space
def has_dup_sort(nums):
    nums_copy = sorted(nums)  # O(n) space -- still!
    for i in range(1, len(nums_copy)):
        if nums_copy[i] == nums_copy[i-1]:
            return True
    return False

# Option 3: truly O(1) extra -- sort in-place
def has_dup_inplace(nums):
    nums.sort()               # modifies original
    for i in range(1, len(nums)):
        if nums[i] == nums[i-1]: return True
    return False

Plantilla para expresar la complejidad total

Indique siempre la respuesta completa: tiempo y espacio: «O(n) de tiempo y O(1) de espacio adicional». Mencione los equilibrios cuando existan. Eso es lo que distingue a los candidatos con más experiencia.

# Complete complexity example: Merge Intervals
def merge_intervals(intervals):
    # Time: O(n log n) for sort + O(n) for merge = O(n log n)
    # Space: O(n) for output (could be n/2 to n intervals)
    intervals.sort(key=lambda x: x[0])  # O(n log n)
    merged = [intervals[0]]
    for start, end in intervals[1:]:
        if start <= merged[-1][1]:
            merged[-1][1] = max(merged[-1][1], end)
        else:
            merged.append([start, end])
    return merged

print(merge_intervals([[1,3],[2,6],[8,10],[15,18]]))
# [[1,6],[8,10],[15,18]]

Comprobación rápida

Comprobación rápida: veamos cómo ha asimilado las ideas sobre complejidad espacial. Está preparado para esto. ✅

Resumen de la lección

Resumen: el espacio auxiliar se cuenta aparte de la entrada, la recursión utiliza un espacio de pila O(profundidad), y el equilibrio entre tiempo y espacio determina la mayoría de las decisiones de diseño de algoritmos.

Gratis para empezar

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 «Complejidad espacial y compensaciones» es gratis?

Sí — el texto completo de «Complejidad espacial y compensaciones» 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 «Complejidad espacial y compensaciones»?

Mida el espacio auxiliar de las pilas de llamadas y las estructuras de datos auxiliares, y reconozca las compensaciones entre tiempo y espacio en la memoización y los algoritmos in-place. 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 4 de 4.

¿Cuánto tiempo toma la lección «Complejidad espacial y compensaciones»?

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

  1. Notación Big-O desde cero
  2. Análisis de bucles y bucles anidados
  3. Recursión y método del árbol de recursión
  4. Complejidad espacial y compensaciones
← Volver a DSA Interview Prep