Knowledge Guide
HomeDSACompany Practice

hard Burst Balloons

Problem Statement

You are given a row of n balloons, each marked with a specific number i.e. ith ballon is marked with nums[i], wheres nums is an integer array. You are asked to burst all the balloons.

When you burst the ith balloon, you get nums[i - 1] * nums[i] * nums[i + 1] coins. If i - 1 or i + 1 indexes are out of bounds of the array, then treat it as if there is a balloon with a 1 painted on it.

Return the highest possible coin total after popping all the balloons.

Examples

Try it yourself

Try solving this question here:

✅ Solution Burst Balloons

Problem Statement

You are given a row of n balloons, each marked with a specific number i.e. ith ballon is marked with nums[i], wheres nums is an integer array. You are asked to burst all the balloons.

When you burst the ith balloon, you get nums[i - 1] * nums[i] * nums[i + 1] coins. If i - 1 or i + 1 indexes are out of bounds of the array, then treat it as if there is a balloon with a 1 painted on it.

Return the highest possible coin total after popping all the balloons.

Examples

  • Example 1:

    • Input: [3, 1, 5]
    • Expected Output: 35
    • Justification: Popping balloon 1 (value 1) first earns 3*1*5=15 coins, leaving [3, 5].Next, pop 3 to earn 1*3*5=15, and finally pop 5 to earn 1*5*1=5, for a total of 15+15+5=35 coins.
  • Example 2:

    • Input: [1, 5, 8]
    • Expected Output: 56
    • Justification: First, pop balloon 1 (value 5), earning 1*5*8=40 coins, leaving [1, 8]. Then, pop balloons 0 and 2, earning 1*1*8=8 and 1*8*1=8 coins respectively, for a total of 40+8+8=56 coins.
  • Example 3:

    • Input: [2, 4, 3, 5]
    • Expected Output: 115
    • Justification: A strategic approach yields the maximum coins: start with balloon 2 (value 3) for 4*3*5=60, then balloon 2 (value 4) for 2*4*5=40, followed by the outer balloons, 1*2*5=10 and 1*5*1=5, summing up to 24+30+10+2=115 coins.

Solution

To solve this problem, a dynamic programming approach is most effective. The key idea is to consider popping balloons in reverse, i.e., imagine adding a balloon back in its place and determining the maximum coins that could be earned up to that point. This reverse thinking helps in simplifying the problem by breaking it down into smaller subproblems, where the solution to each subproblem builds up to the final solution. This method ensures that all potential combinations of bursts are considered without redundant calculations, optimizing both time and space efficiency.

Initially, we approach the problem by considering all possible segments of balloons and determining the maximum coins that can be obtained for each segment. By iteratively expanding the size of these segments and calculating the maximum coins for each, utilizing previously solved smaller segments, we build up to the solution for the entire set of balloons. This bottom-up approach minimizes recalculations and exploits the problem's optimal substructure, making it a fitting strategy for achieving the goal.

Step-by-Step Algorithm

  1. Initialize the DP Table:

    • Create a 2-dimensional array dp, with dimensions (n+2) x (n+2), where n is the number of balloons. This table will hold the maximum coins that can be obtained for bursting all balloons in the subarray defined by its indices. Initialize all cells with 0.
  2. Prepare the Input Array:

    • Construct a new array ballons by adding two extra elements, both 1s, to the beginning and end of the original array nums. This accounts for the edge case where bursting a balloon on one end multiplies its value by 1.
  3. Populate the DP Table:

    • For each possible length of subarray from 1 to n:
      • For each possible starting index left of the subarray:
        • Calculate the ending index right of the subarray based on its length.
        • For each possible position i of the last balloon to burst in the subarray:
          • Compute the coins earned by bursting the ith balloon last. This includes the coins from the burst itself, calculated as ballons[left-1] * ballons[i] * ballons[right+1], plus the maximum coins obtainable from the subarrays to the left and right of i, already stored in dp[left][i-1] and dp[i+1][right].
          • Update dp[left][right] with the maximum of its current value and the newly calculated coins.
  4. Return the Result:

    • The maximum coins obtainable by bursting all balloons is stored in dp[1][n], accounting for the added padding. Return this value as the result.

Algorithm Walkthrough

Let's consider the input: nums = [2, 4, 3, 5]

Initial Setup

  • Extended Array: newNums = [1, 2, 4, 3, 5, 1]
  • DP Table Initialization: A 6x6 matrix filled with zeros.

Iteration Through Subarrays

The process iterates through subarrays of increasing length, calculating the maximum coins that can be obtained by bursting all balloons in each subarray.

Length 1 Subarrays

  • Subarray [2]: (left = 1, right = 1, i = 1)
    • coins = 1*2*4 + 0 + 0 = 8
    • dp[1][1] = 8
  • Subarray [4]: (left = 2, right = 2, i = 2)
    • coins = 2*4*3 + 0 + 0 = 24
    • dp[2][2] = 24
  • Subarray [3]: (left = 3, right = 3, i = 3)
    • coins = 4*3*5 + 0 + 0 = 60
    • dp[3][3] = 60
  • Subarray [5]: (left = 4, right = 4, i = 4)
    • coins = 3*5*1 + 0 + 0 = 15
    • dp[4][4] = 15
[
  [ 0, 0, 0, 0, 0, 0 ],
  [ 0, 8, 0, 0, 0, 0 ],
  [ 0, 0, 24, 0, 0, 0 ],
  [ 0, 0, 0, 60, 0, 0 ],
  [ 0, 0, 0, 0, 15, 0 ],
  [ 0, 0, 0, 0, 0, 0 ]
]

Length 2 Subarrays

  • Subarray [2, 4]:
    • When i = 1 (bursting 2 last): coins = 1*2*3 + 0 + 24 = 30
    • When i = 2 (bursting 4 last): coins = 1*4*3 + 8 + 0 = 20
    • dp[1][2] = 30 (the maximum of the two)
  • Subarray [4, 3]:
    • When i = 2: coins = 2*4*5 + 0 + 60 = 100
    • When i = 3: coins = 2*3*5 + 24 + 0 = 54
    • dp[2][3] = 100
  • Subarray [3, 5]:
    • When i = 3: coins = 4*3*1 + 0 + 15 = 27
    • When i = 4: coins = 4*5*1 + 60 + 0 = 80
    • dp[3][4] = 80
[
  [ 0, 0, 0, 0, 0, 0 ],
  [ 0, 8, 30, 0, 0, 0 ],
  [ 0, 0, 24, 100, 0, 0 ],
  [ 0, 0, 0, 60, 80, 0 ],
  [ 0, 0, 0, 0, 15, 0 ],
  [ 0, 0, 0, 0, 0, 0 ]
]

Length 3 Subarrays

  • Subarray [2, 4, 3]:
    • When i = 1 (bursting 2): coins = 1*2*5 + 0 + 100 = 110
    • When i = 2 (bursting 4): coins = 1*4*5 + 8 + 60 = 88
    • When i = 3 (bursting 3): coins = 1*3*5 + 24 + 0 = 39
    • dp[1][3] = 110
  • Subarray [4, 3, 5]:
    • Similar calculations yield the best outcome for this subarray.
[
  [ 0, 0, 0, 0, 0, 0 ],
  [ 0, 8, 30, 110, 0, 0 ],
  [ 0, 0, 24, 100, 110, 0 ],
  [ 0, 0, 0, 60, 80, 0 ],
  [ 0, 0, 0, 0, 15, 0 ],
  [ 0, 0, 0, 0, 0, 0 ]
]

Full Array [2, 4, 3, 5]

  • Subarray [2, 4, 3, 5]:
    • When i = 1 (bursting 2): coins = 1*2*1 + 0 + 100 = 102
    • When i = 2 (bursting 4): coins = 1*4*1 + 8 + 60 = 72
    • When i = 3 (bursting 3): coins = 1*3*1 + 24 + 0 = 27
    • When i = 4 (bursting 3): coins = 1*5*1 + 110 + 0 = 115
    • dp[1][3] = 115
[
  [ 0, 0, 0, 0, 0, 0 ],
  [ 0, 8, 30, 110, 115, 0 ],
  [ 0, 0, 24, 100, 110, 0 ],
  [ 0, 0, 0, 60, 80, 0 ],
  [ 0, 0, 0, 0, 15, 0 ],
  [ 0, 0, 0, 0, 0, 0 ]
]

Final DP Table Update

  • The process iterates through all subarrays of all possible lengths, filling the DP table with the maximum coins that can be obtained for bursting all balloons in each subarray.
  • The final value, dp[1][4] = 115, gives the maximum coins for bursting all balloons in the array [2, 4, 3, 5].

Code

java
public class Solution {

  public int maxCoins(int[] nums) {
    int n = nums.length;
    // Create an augmented array with 1 on both ends
    int[] balloons = new int[n + 2];
    balloons[0] = balloons[n + 1] = 1;
    for (int i = 0; i < n; i++) {
      balloons[i + 1] = nums[i];
    }

    // DP array to store the maximum coins that can be obtained
    // dp[i][j] represents the maximum coins for popping balloons between i and j, exclusively
    int[][] dp = new int[n + 2][n + 2];

    // Start from smaller subarrays to larger ones
    for (int len = 1; len <= n; len++) {
      for (int start = 1; start <= n - len + 1; start++) {
        int end = start + len - 1;
        // Calculate the max coins by deciding which balloon (k) to pop last in the range [start, end]
        for (int k = start; k <= end; k++) {
          int coins =
            balloons[start - 1] * balloons[k] * balloons[end + 1] +
            dp[start][k - 1] +
            dp[k + 1][end];
          dp[start][end] = Math.max(dp[start][end], coins);
        }
      }
    }

    // The final answer is in dp[1][n]
    return dp[1][n];
  }

  public static void main(String[] args) {
    Solution solution = new Solution();
    // Example 1
    int[] example1 = { 3, 1, 5 };
    System.out.println(
      "Example 1 Expected Output: 35, Actual Output: " +
      solution.maxCoins(example1)
    );

    // Example 2
    int[] example2 = { 1, 5, 8 };
    System.out.println(
      "Example 2 Expected Output: 56, Actual Output: " +
      solution.maxCoins(example2)
    );

    // Example 3
    int[] example3 = { 2, 4, 3, 5 };
    System.out.println(
      "Example 3 Expected Output: 115, Actual Output: " +
      solution.maxCoins(example3)
    );
  }
}

Complexity Analysis

Time Complexity

The time complexity of this algorithm is , where (n) is the number of balloons. This complexity arises because:

  1. We iterate over each possible subarray of balloons (n choices).
  2. For each subarray, we iterate over all possible positions of the last balloon to burst (n choices again).
  3. For each choice of the last balloon, we perform a calculation that includes accessing and updating entries in our dynamic programming table, which is itself indexed by two parameters (the left and right bounds of the subarray).

Therefore, the nested loops result in time complexity.

Space Complexity

The space complexity of the algorithm is due to the dynamic programming table (dp), which stores the maximum coins obtainable for every possible subarray of balloons.

🤖 Don't fully get this? Learn it with Claude

Stuck on Burst Balloons? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Burst Balloons** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Burst Balloons** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Burst Balloons**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Burst Balloons**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes