#0299Time: Exponential, roughly `O(n * C_n)` where `C_n` is the n-th Catalan number. This is because the recursion tree branches extensively, leading to a number of calls that grows exponentially with `n`.Space: `O(n)` for the recursion call stack depth.5 companies
You are given n balloons, indexed from 0 to n - 1. Each balloon is painted with a number on it represented by an array nums. You are asked to burst all the balloons.
If you burst the ith balloon, you will get nums[i - 1] * nums[i] * nums[i + 1] coins. If i - 1 or i + 1 goes out of bounds of the array, then treat it as if there is a balloon with a 1 painted on it.
Return the maximum coins you can collect by bursting the balloons wisely.
3 approaches with complexity analysis and trade-offs.
The problem can be reframed by thinking about the last balloon to be burst in a given range. A brute-force recursive approach can be designed based on this idea. For any range of balloons, we try every balloon as the last one to burst, calculate the coins, and recursively solve the subproblems on its left and right. This method explores all possibilities but is highly inefficient due to redundant calculations.
Algorithm
Pad the nums array with 1s at both ends to create new_nums.
The core idea is to not think about which balloon to burst first, but which to burst last. If we decide balloon k is the last one to burst in an interval (left, right), all other balloons in this interval must have been burst already. This means its neighbors are the boundary balloons at left and right. The coins gained from this last burst are nums[left] * nums[k] * nums[right]. The total coins would be this value plus the maximum coins from bursting all balloons in (left, k) and (k, right) independently.
This naturally leads to a recursive solution. We define a function solve(left, right) that computes the maximum coins from bursting all balloons between indices left and right (exclusive). To handle boundary conditions gracefully, we pad the original nums array with 1s at both ends.
The function iterates through all possible k as the last balloon to burst in (left, right) and recursively calls itself for the sub-ranges (left, k) and (k, right). The maximum value over all choices of k is the result for solve(left, right).
1class Solution {2 public int maxCoins(int[] nums) {3 int n = nums.length;4 // Create a new array with virtual balloons (value 1) at the boundaries.5 int[] newNums = new int[n + 2];6 newNums[0] = 1;7 newNums[n + 1] = 1;8 for (int i = 0; i < n; i++) {9 newNums[i + 1] = nums[i];10 }11 // The problem is now to find the max coins for the range (0, n+1).12 return solve(newNums, 0, n + 1);13 }1415 private int solve(int[] nums, int left, int right) {16 // Base case: If there are no balloons to burst, return 0 coins.17 if (left + 1 >= right) {18 return 0;19 }2021 int maxCoins = 0;22 // Iterate through each balloon 'k' in the range (left, right)23 // and consider it as the last one to be burst.24 for (int k = left + 1; k < right; k++) {25 // Coins from bursting 'k' last.26 int currentCoins = nums[left] * nums[k] * nums[right];27 // Add coins from recursively solving the subproblems.28 currentCoins += solve(nums, left, k) + solve(nums, k, right);29 // Update the maximum coins found so far.30 maxCoins = Math.max(maxCoins, currentCoins);31 }32 return maxCoins;33 }34}
Complexity
Time
Exponential, roughly `O(n * C_n)` where `C_n` is the n-th Catalan number. This is because the recursion tree branches extensively, leading to a number of calls that grows exponentially with `n`.
Space
`O(n)` for the recursion call stack depth.
Trade-offs
Pros
Conceptually simple if you reframe the problem correctly.
Cons
Extremely inefficient due to massive redundant computations.
Will result in a 'Time Limit Exceeded' error on most platforms for non-trivial inputs.
Solutions
Solution
1class Solution { public int maxCoins ( int [] nums ) { int [] vals = new int [ nums . length + 2 ]; vals [ 0 ] = 1 ; vals [ vals . length - 1 ] = 1 ; System . arraycopy ( nums , 0 , vals , 1 , nums . length ); int n = vals . length ; int [][] dp = new int [ n ][ n ]; for ( int l = 2 ; l < n ; ++ l ) { for ( int i = 0 ; i + l < n ; ++ i ) { int j = i + l ; for ( int k = i + 1 ; k < j ; ++ k ) { dp [ i ][ j ] = Math . max ( dp [ i ][ j ], dp [ i ][ k ] + dp [ k ][ j ] + vals [ i ] * vals [ k ] * vals [ j ]); } } } return dp [ 0 ][ n - 1 ]; } }
Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.