Burst Balloons: Reverse Interval DP
Solve the burst-balloons problem by thinking in reverse — choosing the last balloon to burst in each interval rather than the first.
Burst Balloons: Reverse Interval DP is a free DSA Interview Prep lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the DSA Interview Prep learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Burst Balloons Problem
Given n balloons with values nums, bursting balloon i earns nums[i-1] * nums[i] * nums[i+1] coins (the product of itself and its current neighbours). After it bursts, the neighbours become adjacent. Find the maximum coins you can collect by bursting all balloons. The naive simulation is hard because bursting changes neighbours — Reverse interval DP elegantly sidesteps this difficulty.
Why Forward Simulation Fails
If we try to define dp[i][j] as maximum coins from bursting balloons in range [i, j] and think about which balloon to burst first, we face a problem: bursting balloon k first means nums[k-1] and nums[k+1] must be the current neighbours — but those balloons might be burst later, changing neighbours dynamically. The state is hard to define cleanly in the forward direction.
The Key Insight: Think in Reverse
The trick is to think about which balloon is the last to burst in interval [i, j]. When balloon k is the last burst in [i, j], all other balloons in [i, j] are already gone. So balloon k's neighbours are exactly nums[i-1] and nums[j+1] — the boundary balloons just outside the interval. This makes the coin calculation for the last burst deterministic: it does not depend on the order of earlier bursts.
State and Recurrence Definition
Add sentinel balloons: prepend and append 1 to nums to form nums = [1] + nums + [1]. Define dp[i][j] as the maximum coins from bursting all balloons strictly between indices i and j (exclusive), where nums[i] and nums[j] are the surviving boundary balloons. Recurrence: for each candidate last balloon k in (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]Full Implementation
We pad the array with sentinels, initialise the DP table to zero (empty interval = 0 coins), and fill in increasing interval length. The final answer is dp[0][n+1], representing the maximum coins from bursting all original balloons with the sentinels as permanent boundaries.
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])) # 167Tracing Through the Example
For [3, 1, 5, 8], padded to [1, 3, 1, 5, 8, 1] (indices 0-5). We want dp[0][5]. For length=2 intervals (one balloon inside): 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. Building up, the optimal is to burst 1 last among {3,1,5,8} after bursting neighbours first, giving 167 total coins.
Complexity Analysis
There are O(n²) intervals and for each interval we try O(n) split points, giving O(n³) time complexity. Space is O(n²) for the DP table. For n = 500 balloons, this is 125 million operations — feasible for interview constraints. The sentinel padding simplifies boundary handling: without it, you'd need explicit checks for whether i-1 and j+1 are in bounds.
Memoised Top-Down Alternative
The same solution can be written top-down with @lru_cache, which may be more intuitive to derive during an interview. Define solve(i, j) as max coins in open interval (i, j). The function tries all k as the last burst and memoises results. Both approaches have identical time and space complexity.
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])) # 167Common Mistake: Forward DP Definition
A common mistake is defining dp[i][j] as coins when the first balloon in [i,j] is burst, not the last. This fails because the coin calculation for the first burst depends on neighbouring balloons that haven't been burst yet — and the state of those neighbours changes as the algorithm progresses. Always think about the last element in interval DP when boundaries depend on remaining elements.
Why Sentinel Values of 1?
Sentinels of value 1 are chosen because they act as neutral elements for multiplication. When a boundary balloon is the last to burst, its coin value is boundary * last * boundary = 1 * last * 1 = last. Using 0 would give 0 coins (wrong), and using other values would distort the computation. The sentinel trick cleanly unifies all boundary cases without special-casing the leftmost and rightmost balloons.
Contrast with Standard Interval DP
In standard interval DP (matrix chain), the split point k represents where we divide the problem into two sub-problems solved independently. In Burst Balloons, k is the last to burst in the interval, making the two sub-intervals [i,k] and [k,j] independent given that k is still present as a boundary. This reversed perspective is the creative insight that makes burst balloons solvable by interval DP.
Quick Check
Test your understanding of Data Structures & Algorithms — Coding Interview Prep concepts from this lesson.
Lesson Recap
In this lesson you learned: forward simulation fails because bursting balloons changes neighbours unpredictably, the reverse insight defines k as the last balloon burst in an interval, making neighbours nums[i] and nums[j], and the recurrence dp[i][j] = max(dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j]) with sentinel padding gives an O(n³) solution. Next up we shift to knapsack DP, starting with the classic 0/1 knapsack and its space optimisation.
Frequently asked questions
Is the “Burst Balloons: Reverse Interval DP” lesson free?
Yes — the full text of “Burst Balloons: Reverse Interval DP” is free to read here on the web, and the DSA Interview Prep course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the DSA Interview Prep course, upgrade to CoddyKit PRO.
What will I learn in “Burst Balloons: Reverse Interval DP”?
Solve the burst-balloons problem by thinking in reverse — choosing the last balloon to burst in each interval rather than the first. You practise DSA Interview Prep with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start DSA Interview Prep?
No prior experience is required. DSA Interview Prep on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Burst Balloons: Reverse Interval DP” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this DSA Interview Prep lesson?
Yes. Every DSA Interview Prep lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Interval DP Pattern and Fill Order
- Longest Palindromic Subsequence and Substring
- Palindrome Partitioning II
- Burst Balloons: Reverse Interval DP