Patrón de PD por intervalos y orden de llenado
Defina el estado de PD por intervalos dp[i][j], explique por qué los intervalos deben rellenarse en orden creciente de longitud y siga el patrón en la multiplicación de cadenas de matrices.
Patrón de PD por intervalos y orden de llenado es una lección gratuita de Coding 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 Coding Interview Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Coding Interview Prep incluye 4 lecciones en total.
¿Qué es la DP de intervalos?
La DP de intervalos es un patrón de programación dinámica en el que el estado dp[i][j] representa la respuesta óptima para el subproblema que abarca los índices i a j. La idea clave es resolver primero los intervalos más pequeños y ampliar progresivamente la solución hasta cubrir todo el rango. Este patrón modela de forma natural problemas como la multiplicación de cadenas de matrices, la partición de palíndromos y el reventado de globos, en los que los límites del subproblema son los extremos izquierdo y derecho de un rango.
Definición del estado y casos base
En la DP de intervalos, el estado es dp[i][j], donde i <= j. Los casos base son los intervalos de un solo elemento: dp[i][i]. Se resuelven trivialmente; por ejemplo, una sola matriz tiene un coste de multiplicación igual a cero. Los intervalos de dos elementos, dp[i][i+1], también suelen tener respuestas sencillas. Rellenamos la tabla con longitudes de intervalo crecientes, desde la longitud 1 hasta n.
n = 4
dp = [[0] * n for _ in range(n)]
# Base cases: single elements
for i in range(n):
dp[i][i] = 0 # length-1 intervalsOrden de llenado: longitud creciente
El detalle fundamental de la DP de intervalos es el orden de llenado. Debemos calcular todos los intervalos de longitud L antes de calcular los intervalos de longitud L+1, porque un intervalo más largo depende de subintervalos más cortos. El bucle externo recorre la longitud del intervalo de 2 a n; el bucle intermedio establece el límite izquierdo i; y deducimos el límite derecho mediante j = i + L - 1.
n = 5
dp = [[float('inf')] * n for _ in range(n)]
for i in range(n):
dp[i][i] = 0
for length in range(2, n + 1): # interval length
for i in range(n - length + 1): # left boundary
j = i + length - 1 # right boundary
for k in range(i, j): # split point
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j])Configuración de la multiplicación de cadenas de matrices
El problema clásico de DP de intervalos es la multiplicación de cadenas de matrices: dadas matrices con dimensiones dims[0..n], encuentre el número mínimo de multiplicaciones escalares necesarias para calcular el producto. Multiplicar la matriz A(p×q) por la matriz B(q×r) cuesta p*q*r operaciones. dp[i][j] = coste mínimo de multiplicar las matrices desde i hasta j. El punto de división k determina dónde se divide la secuencia en dos subcadenas.
def matrix_chain_order(dims):
n = len(dims) - 1 # number of matrices
dp = [[0] * n for _ in range(n)]
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
dp[i][j] = float('inf')
for k in range(i, j):
cost = dp[i][k] + dp[k+1][j] + dims[i]*dims[k+1]*dims[j+1]
dp[i][j] = min(dp[i][j], cost)
return dp[0][n-1]
print(matrix_chain_order([10, 30, 5, 60])) # 4500Seguimiento de la tabla de DP
Recorramos el ejemplo de la cadena de matrices con las dimensiones [10, 30, 5, 60], que representa tres matrices: A(10×30), B(30×5) y C(5×60). Para dp[0][2], probamos la división en k=0: dp[0][0] + dp[1][2] + 10×30×60 = 0 + 9000 + 18000 = 27000, y en k=1: dp[0][1] + dp[2][2] + 10×5×60 = 1500 + 0 + 3000 = 4500. Por tanto, dp[0][2] = 4500, que se obtiene multiplicando AB primero.
Por qué funciona este orden de llenado
Al calcular dp[i][j], consultamos dp[i][k] y dp[k+1][j] para todos los valores de k en [i, j-1]. Ambos subintervalos tienen una longitud estrictamente menor que [i, j]. Al recorrer las longitudes de menor a mayor, todos los subintervalos necesarios se calculan antes de necesitarlos. Este es el argumento fundamental de corrección del orden de llenado de la DP de intervalos: los intervalos más cortos siempre son dependencias de los más largos.
DP de intervalos de arriba abajo con memoización
Como alternativa, la DP de intervalos se puede implementar de arriba abajo con memoización. Escribimos una función recursiva solve(i, j) que devuelve el coste óptimo del intervalo [i, j] y guardamos los resultados en un diccionario. La recursión gestiona automáticamente el orden de llenado. El enfoque de arriba abajo suele ser más fácil de razonar, pero puede tener sobrecarga por las llamadas a funciones; el enfoque de abajo arriba es más rápido en la práctica para entradas grandes.
from functools import lru_cache
def matrix_chain_memo(dims):
n = len(dims) - 1
@lru_cache(maxsize=None)
def solve(i, j):
if i == j:
return 0
return min(
solve(i, k) + solve(k+1, j) + dims[i]*dims[k+1]*dims[j+1]
for k in range(i, j)
)
return solve(0, n-1)
print(matrix_chain_memo([10, 30, 5, 60])) # 4500Complejidad temporal y espacial
La DP de intervalos tiene O(n²) estados (todos los pares (i, j)) y cada estado recorre O(n) puntos de división, lo que da un total de O(n³) de tiempo. El espacio es O(n²) para la tabla de DP. Para la multiplicación de cadenas de 100 matrices, esto supone 1.000.000 de operaciones, una cantidad perfectamente viable. El patrón aparece en muchos problemas difíciles de LeetCode y es uno de los favoritos en las entrevistas de FAANG debido a su estructura poco evidente.
Reconstrucción de la solución óptima
Para reconstruir la parentización real (no solo el coste), guarde una tabla independiente split[i][j] que registre qué valor de k consiguió el mínimo en cada estado. Después, lea las divisiones recursivamente: reconstruct(i, j) muestra la agrupación óptima recurriendo sobre [i, split[i][j]] y [split[i][j]+1, j]. Esta técnica se aplica a todos los problemas de DP de intervalos.
def matrix_chain_with_split(dims):
n = len(dims) - 1
dp = [[0]*n for _ in range(n)]
split = [[0]*n for _ in range(n)]
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
dp[i][j] = float('inf')
for k in range(i, j):
cost = dp[i][k] + dp[k+1][j] + dims[i]*dims[k+1]*dims[j+1]
if cost < dp[i][j]:
dp[i][j] = cost
split[i][j] = k
return dp[0][n-1], splitPlantilla para cualquier problema de DP de intervalos
La plantilla universal de DP de intervalos consta de tres partes: (1) inicializar los casos base para elementos individuales; (2) recorrer longitudes crecientes y, para cada longitud, recorrer los límites izquierdos válidos calculando el límite derecho; y (3) para cada intervalo, recorrer todos los puntos de división y aplicar la recurrencia específica del problema. Lo único que cambia entre problemas es la fórmula de recurrencia dentro del bucle más interno.
def interval_dp_template(n, base_cost, split_cost):
dp = [[float('inf')] * n for _ in range(n)]
for i in range(n):
dp[i][i] = base_cost(i) # problem-specific base case
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
for k in range(i, j):
# problem-specific recurrence
candidate = dp[i][k] + dp[k+1][j] + split_cost(i, k, j)
dp[i][j] = min(dp[i][j], candidate)
return dp[0][n-1]Problemas habituales de DP de intervalos
Entre los problemas que utilizan DP de intervalos se incluyen: Multiplicación de cadenas de matrices (minimizar operaciones), Reventar globos (maximizar monedas), Impresora extraña (minimizar operaciones de impresión), Triangulación de un polígono con puntuación mínima y Partición de palíndromos II. Todos utilizan la misma estructura de orden de llenado, pero con recurrencias diferentes. Reconozca el patrón cuando un problema solicite un valor óptimo sobre un rango o una secuencia que se pueda dividir en cualquier punto interior.
Comprobación rápida
Compruebe su comprensión de los conceptos de Data Structures & Algorithms — Coding Interview Prep de esta lección.
Resumen de la lección
En esta lección ha aprendido que: la DP de intervalos utiliza dp[i][j] para representar la respuesta óptima sobre un rango; el orden de llenado debe seguir longitudes de intervalo crecientes para calcular primero los subintervalos; y la plantilla universal tiene una complejidad temporal de O(n³) y espacial de O(n²). A continuación exploraremos la subsecuencia y la subcadena palindrómicas más largas utilizando este mismo patrón.
Preguntas frecuentes
¿La lección «Patrón de PD por intervalos y orden de llenado» es gratis?
Sí — el texto completo de «Patrón de PD por intervalos y orden de llenado» 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 Coding Interview Prep, actualiza a CoddyKit PRO. El curso de Coding Interview Prep incluye 4 lecciones en total.
¿Qué aprenderé en «Patrón de PD por intervalos y orden de llenado»?
Defina el estado de PD por intervalos dp[i][j], explique por qué los intervalos deben rellenarse en orden creciente de longitud y siga el patrón en la multiplicación de cadenas de matrices. Practicas Coding 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 Coding Interview Prep?
No se requiere experiencia previa. Coding 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 «Patrón de PD por intervalos y orden de llenado»?
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 Coding Interview Prep?
Sí. Cada lección de Coding 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
- Patrón de PD por intervalos y orden de llenado
- Subsecuencia y subcadena palindrómicas más largas
- Palindrome Partitioning II
- Burst Balloons: PD por intervalos en sentido inverso