-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
0312-burst-balloons.cpp
52 lines (45 loc) · 1.8 KB
/
0312-burst-balloons.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
Given array of balloons w/ coins, if burst ith, get (i-1) + i + (i+1) coins
Return max coins can collect by bursting the balloons wisely
DP to return max coins obtainable in each interval [left, right]
Divide & conquer left & right depends on previous bursts, so think backwards
Instead of which one to burst first, need to think which one to burst last
Time: O(n^3) -> O(n^2) states, for each states, determining max coins is O(n)
Space: O(n^2) -> O(n^2) to store all states
*/
class Solution {
public:
int maxCoins(vector<int>& nums) {
// add 1 before & after nums
nums.insert(nums.begin(), 1);
nums.insert(nums.end(), 1);
int n = nums.size();
// cache results of dp
vector<vector<int>> memo(n, vector<int>(n, 0));
// 1 & n - 2 since we can't burst our fake balloons
return dp(nums, memo, 1, n - 2);
}
private:
int dp(vector<int>& nums, vector<vector<int>>& memo, int left, int right) {
// base case interval is empty, yields 0 coins
if (right - left < 0) {
return 0;
}
// we've already seen this, return from cache
if (memo[left][right] > 0) {
return memo[left][right];
}
// find the last burst in nums[left]...nums[right]
int result = 0;
for (int i = left; i <= right; i++) {
// nums[i] is the last burst
int curr = nums[left - 1] * nums[i] * nums[right + 1];
// nums[i] is fixed, recursively call left & right sides
int remaining = dp(nums, memo, left, i - 1) + dp(nums, memo, i + 1, right);
result = max(result, curr + remaining);
}
// add to cache
memo[left][right] = result;
return result;
}
};