0Pricing
DSA Interview Prep · Lección

Burst Balloons: PD por intervalos en sentido inverso

Resuelva el problema burst-balloons pensando al revés: elija el último globo que explota en cada intervalo en lugar del primero.

Burst Balloons: PD por intervalos en sentido inverso 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.

El problema de reventar globos

Dadas n globos con valores nums, reventar el globo i proporciona nums[i-1] * nums[i] * nums[i+1] monedas (el producto de su propio valor y el de sus vecinos actuales). Después de reventarlo, sus vecinos pasan a ser adyacentes. Encuentre el máximo de monedas que puede obtener al reventar todos los globos. La simulación ingenua es difícil porque reventar un globo cambia los vecinos; la DP de intervalos en sentido inverso evita elegantemente esta dificultad.

Por qué falla la simulación hacia delante

Si intentamos definir dp[i][j] como el máximo de monedas obtenido al reventar los globos del intervalo [i, j] y pensamos en qué globo reventar primero, nos encontramos con un problema: reventar primero el globo k implica que nums[k-1] y nums[k+1] deben ser sus vecinos actuales, pero esos globos podrían reventarse después, lo que cambiaría los vecinos dinámicamente. El estado es difícil de definir claramente en la dirección hacia delante.

La idea clave: pensar en sentido inverso

El truco consiste en pensar en qué globo será el último en reventarse dentro del intervalo [i, j]. Cuando el globo k es el último en reventarse en [i, j], todos los demás globos de [i, j] ya han desaparecido. Por lo tanto, los vecinos del globo k son exactamente nums[i-1] y nums[j+1]: los globos frontera situados justo fuera del intervalo. Esto hace que el cálculo de monedas del último reventado sea determinista: no depende del orden de los reventados anteriores.

Definición del estado y la recurrencia

Añada globos centinela: anteponga y añada 1 a nums para formar nums = [1] + nums + [1]. Defina dp[i][j] como el máximo de monedas obtenido al reventar todos los globos situados estrictamente entre los índices i y j (exclusivos), donde nums[i] y nums[j] son los globos frontera que permanecen. Recurrencia: para cada posible último globo k en (i, j): dp[i][j] = max(dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j]).

# With sentinels: nums = [1] + original + [1]
# dp[i][j] = max coins from bursting all balloons in open interval (i, j)
# k = last balloon to burst in (i,j)
# dp[i][j] = max over k in (i,j): dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j]

Implementación completa

Rellenamos el arreglo con centinelas, inicializamos la tabla de DP con ceros (un intervalo vacío equivale a 0 monedas) y la rellenamos aumentando la longitud de los intervalos. La respuesta final es dp[0][n+1], que representa el máximo de monedas obtenido al reventar todos los globos originales, con los centinelas como fronteras permanentes.

def maxCoins(nums):
    nums = [1] + nums + [1]
    n = len(nums)
    dp = [[0]*n for _ in range(n)]
    
    # length of open interval (i, j) exclusive: j - i - 1 balloons inside
    for length in range(2, n):       # length = j - i
        for i in range(0, n - length):
            j = i + length
            for k in range(i+1, j):  # k is last burst in (i, j)
                coins = dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j]
                dp[i][j] = max(dp[i][j], coins)
    
    return dp[0][n-1]

print(maxCoins([3, 1, 5, 8]))  # 167

Recorrido del ejemplo

Para [3, 1, 5, 8], rellenado con centinelas para obtener [1, 3, 1, 5, 8, 1] (índices del 0 al 5). Queremos dp[0][5]. Para intervalos de longitud 2 (un globo en el interior): dp[0][2] = 1*3*1=3, dp[1][3]=3*1*5=15, dp[2][4]=1*5*8=40, dp[3][5]=5*8*1=40. Al avanzar, la solución óptima consiste en reventar el 1 en último lugar entre {3,1,5,8}, después de reventar primero sus vecinos, lo que produce un total de 167 monedas.

Análisis de complejidad

Hay O(n²) intervalos y, para cada intervalo, probamos O(n) puntos de división, lo que da una complejidad temporal de O(n³). El espacio es O(n²) para la tabla de DP. Para n = 500 globos, esto supone 125 millones de operaciones, una cantidad viable para las restricciones de una entrevista. El relleno con centinelas simplifica la gestión de los límites: sin él, tendría que comprobar explícitamente si i-1 y j+1 están dentro de los límites.

Alternativa memoizada de arriba abajo

La misma solución puede escribirse de arriba abajo con @lru_cache, lo que puede resultar más intuitivo de deducir durante una entrevista. Defina solve(i, j) como el máximo de monedas en el intervalo abierto (i, j). La función prueba todos los valores de k como último globo reventado y memoriza los resultados. Ambos enfoques tienen la misma complejidad temporal y espacial.

from functools import lru_cache

def maxCoins_memo(nums):
    nums = [1] + nums + [1]
    n = len(nums)
    
    @lru_cache(maxsize=None)
    def solve(i, j):
        if j - i < 2:  # no balloons between i and j
            return 0
        return max(
            solve(i, k) + solve(k, j) + nums[i]*nums[k]*nums[j]
            for k in range(i+1, j)
        )
    
    return solve(0, n-1)

print(maxCoins_memo([3, 1, 5, 8]))  # 167

Error común: definir la DP hacia delante

Un error común consiste en definir dp[i][j] como las monedas obtenidas cuando se revienta el primer globo de [i,j], en lugar del último. Esto falla porque el cálculo de monedas del primer reventado depende de globos vecinos que todavía no se han reventado, y el estado de esos vecinos cambia a medida que avanza el algoritmo. Piense siempre en el último elemento en la DP de intervalos cuando los límites dependen de los elementos restantes.

¿Por qué valores centinela de 1?

Se eligen centinelas con valor 1 porque actúan como elementos neutros de la multiplicación. Cuando un globo frontera es el último en reventarse, el valor de sus monedas es boundary * last * boundary = 1 * last * 1 = last. Usar 0 produciría 0 monedas (incorrecto), mientras que usar otros valores distorsionaría el cálculo. El truco de los centinelas unifica claramente todos los casos de frontera sin tener que tratar de forma especial los globos situados en los extremos izquierdo y derecho.

Comparación con la DP de intervalos estándar

En la DP de intervalos estándar (multiplicación de cadenas de matrices), el punto de división k representa el lugar donde dividimos el problema en dos subproblemas resueltos de forma independiente. En Burst Balloons, k es el último globo en reventarse del intervalo, lo que hace que los dos subintervalos [i,k] y [k,j] sean independientes, dado que k sigue presente como frontera. Esta perspectiva inversa es la idea creativa que permite resolver Burst Balloons mediante DP de intervalos.

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: la simulación hacia delante falla porque hacer explotar globos cambia los vecinos de forma impredecible, la idea inversa define k como el último globo que explota en un intervalo, lo que convierte a los vecinos en nums[i] y nums[j], y la recurrencia dp[i][j] = max(dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j]) con relleno de centinelas proporciona una solución O(n³). A continuación pasaremos a la programación dinámica de la mochila, empezando por la mochila clásica 0/1 y su optimización espacial.

Preguntas frecuentes

¿La lección «Burst Balloons: PD por intervalos en sentido inverso» es gratis?

Sí — el texto completo de «Burst Balloons: PD por intervalos en sentido inverso» 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 «Burst Balloons: PD por intervalos en sentido inverso»?

Resuelva el problema burst-balloons pensando al revés: elija el último globo que explota en cada intervalo en lugar del primero. 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 «Burst Balloons: PD por intervalos en sentido inverso»?

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. Patrón de PD por intervalos y orden de llenado
  2. Subsecuencia y subcadena palindrómicas más largas
  3. Palindrome Partitioning II
  4. Burst Balloons: PD por intervalos en sentido inverso
← Volver a DSA Interview Prep