Last Updated: March 28, 2026
We have a row of balloons, each with a value. When we burst a balloon, we earn coins equal to the product of that balloon's value with its two neighbors. After bursting, the neighbors of the burst balloon become adjacent to each other. We need to find the order of bursting that maximizes total coins.
What makes this problem tricky is that bursting a balloon changes the neighborhood of every remaining balloon. If you burst balloon i, suddenly balloons i-1 and i+1 become neighbors. So the coins you earn from bursting balloon i+1 later depend on whether you already burst balloon i. The order of operations matters enormously, and every decision ripples forward.
The key observation: instead of thinking about which balloon to burst first, think about which balloon to burst last in a given range. If balloon k is the last one burst in the range (left, right), then when we burst it, its neighbors are exactly left and right (the boundaries). Everything else in that range is already gone. This "last burst" perspective eliminates the dependency problem and gives us clean subproblems.
1 <= n <= 300 → With up to 300 balloons, we need O(n^3) or better. An O(n^3) interval DP fits perfectly within limits.0 <= nums[i] <= 100 → Values are non-negative. The maximum product for any single burst is 100 100 100 = 1,000,000. With 300 balloons, total coins fit comfortably in a 32-bit integer.The most direct approach is to try every possible order of bursting. There are n balloons, so there are n! possible orderings. For each ordering, simulate the bursting process, calculate the total coins, and keep track of the maximum.
This is what you would naturally think of first. Pick a balloon to burst, compute the coins (using its current neighbors), remove it from the list, and recurse on the remaining balloons. Try every balloon as the first to burst, then every remaining balloon as the second, and so on.
Input: nums = [3, 1, 5, 8]
One possible bursting order: burst index 1 (value 1), then index 0 (value 3), then index 1 (value 5, now adjacent to boundary 1 and 8), then index 0 (value 8).
Total = 15 + 120 + 24 + 8 = 167. The brute force tries all n! orderings and returns the max.
We are trying every permutation, which is astronomically slow. Many different orderings lead to the same remaining set of balloons, but we recompute from scratch each time. Can we define subproblems over contiguous ranges instead?
The brute force stumbles because bursting a balloon changes the neighbors of every remaining balloon. Here is the mental shift that unlocks this problem: instead of asking "which balloon should I burst first?", ask "which balloon should I burst last in this range?"
If balloon k is the last balloon burst in the range between boundaries left and right, then at the moment we burst k, every other balloon in that range is already gone. The only balloons still standing near k are left and right themselves (the boundaries). So the coins from bursting k are exactly nums[left] * nums[k] * nums[right].
Everything to the left of k (between left and k) forms its own independent subproblem, and everything to the right of k (between k and right) forms another. These two subproblems do not interact because k is still standing while they are being resolved.
To make the boundary logic clean, pad the original array with 1s on both ends: [1, nums[0], nums[1], ..., nums[n-1], 1]. Define dp[left][right] as the maximum coins obtainable by bursting all balloons strictly between indices left and right (exclusive). The answer is dp[0][n+1].
The "last burst" trick resolves the core difficulty. When you think forward ("which balloon to burst first?"), bursting balloon i changes the neighbors of i-1 and i+1, creating a cascading dependency that makes it impossible to split the problem into independent pieces. But when you think backward ("which balloon to burst last in this range?"), the balloon you burst last has known neighbors (the range boundaries), and everything inside the range has already been handled by the two independent subproblems on either side of it.
This is a classic interval DP pattern. The subproblems are defined over contiguous ranges, and we build up from smaller ranges to larger ones. Each range of length L depends only on ranges of length less than L, so the bottom-up ordering is correct.
vals = [1] + nums + [1]. Let m = len(vals).m x m, initialized to 0.(left, right) of the current length, try every balloon k between left+1 and right-1 as the last burst.k: dp[left][right] = max(dp[left][right], dp[left][k] + vals[left] * vals[k] * vals[right] + dp[k][right]).dp[0][m-1].This bottom-up approach fills every interval systematically. Can we express the same recurrence top-down, which is often easier to code correctly in an interview?
The idea is identical to Approach 2: solve(left, right) returns the maximum coins from bursting all balloons strictly between left and right. We try each k as the last burst and take the maximum. The only difference is we recurse instead of looping over interval lengths, and memoize results.
Many people find this version easier to write under interview pressure because you do not need to think about the order of filling the table. Just write the recurrence naturally and let the recursion handle dependencies.
vals = [1] + nums + [1].solve(left, right): if right - left < 2, return 0. Otherwise, try each k from left+1 to right-1, compute solve(left, k) + vals[left]*vals[k]*vals[right] + solve(k, right), and return the max.solve(0, m-1).The recursive calls mirror the bottom-up table exactly. For nums = [3, 1, 5, 8], solve(0, 5) tries k=1,2,3,4. For k=4, it calls solve(0, 4) and solve(4, 5). The recursion bottoms out at intervals with no balloons between boundaries. The memoization ensures each subproblem is solved once, yielding the same answer: 167.