Burst Balloons

HardDynamic Programming · Interval DP🧩 Grid DPLeetCode #312 ↗Updated

Problem

Balloons in a row carry numbers nums[i]. Bursting balloon i earns left × nums[i] × right, where left and right are its current neighbours (a missing neighbour counts as 1); afterwards those neighbours become adjacent. Burst every balloon and return the maximum total coins.
Inputnums = [3,1,5,8]Output167 (3·1·5 + 3·5·8 + 1·3·8 + 1·8·1)
Inputnums = [1,5]Output10

1 ≤ n ≤ 300  ·  0 ≤ nums[i] ≤ 100

Try it yourself

Java
class Solution {
    public int maxCoins(int[] nums) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Choosing the first balloon to burst tangles both sides together. Choose the last balloon k in an open interval (l, r) instead: while it survives, the two sides are independent, and when it finally pops its neighbours are exactly the fixed walls l and r.
PatternGrid DP

Instinct Grid moves that never loop back (right/down, row to row) plus "count or optimise the paths" - build dp[r][c] from the cells that can step in.

Memory hack Every cell asks its parents - a cell's answer comes only from the neighbours that can move into it, so fill cells in the order they arrive.

Open the Grid DP guide →

Approaches

Brute ForceTry Every Bursting Order

Time O(n · n!)Space O(n)

Simulate the game: at each step pick any remaining balloon, collect its coins from its current neighbours, remove it, and recurse on the shorter row. Put it back afterwards (backtracking). Every permutation of bursts is explored.

Java
public int maxCoins(int[] nums) {
    List<Integer> row = new ArrayList<>();
    for (int x : nums) row.add(x);
    return burstAll(row);
}

private int burstAll(List<Integer> row) {
    int best = 0;
    for (int i = 0; i < row.size(); i++) {
        int left = i > 0 ? row.get(i - 1) : 1;
        int right = i < row.size() - 1 ? row.get(i + 1) : 1;
        int gain = left * row.get(i) * right;
        int removed = row.remove(i);
        best = Math.max(best, gain + burstAll(row));
        row.add(i, removed); // undo
    }
    return best;
}

Faithful to the rules and easy to trust, but factorial — n = 10 is already slow.

At a glance

LevelApproachTimeSpace
Brute ForceTry Every Bursting OrderO(n · n!)O(n)
BetterMemoized Interval Recursion (Last Balloon)O(n³)O(n²)
OptimalBottom-Up Interval DP by LengthO(n³)O(n²)
Common pitfalls
  • Splitting on the first balloon burst — its sub-rows are not independent.
  • Forgetting the virtual 1s at both ends (and the open-interval meaning of l, r).
  • Iterating l from left to right without ordering by length — reads unfilled cells.
Interview tips
  • Show a 3-balloon example where greedy (smallest first) fails before reaching for DP.
  • Say out loud why “last burst” makes subproblems independent.
  • Define dp[l][r] precisely (exclusive bounds) before writing any loops.
Pattern
Interval DP → an operation on a range whose cost depends on its current neighbours; fix the last split point.
My notes saved in this browser