解法一:记忆化搜索
参见官方题解:https://leetcode-cn.com/problems/burst-balloons/solution/chuo-qi-qiu-by-leetcode-solution/
class Solution {
// ans[left][right]表示开区间(i, j)内的气球都填满后得到的最大硬币数
private int[][] ans;
// val[i]表示第i个位置上的值, 左右边界均为1
private int[] val;
public int maxCoins(int[] nums) {
int n = nums.length;
val = new int[n + 2];
for (int i = 0; i < n; ++i) {
val[i + 1] = nums[i];
}
val[0] = val[n + 1] = 1;
ans = new int[n + 2][n + 2];
for (int[] i : ans) {
Arrays.fill(i, -1);
}
return solve(0, n + 1);
}
private int solve(int left, int right) {
if (left >= right - 1) {
return 0;
}
if (ans[left][right] != -1) {
return ans[left][right];
}
for (int i = left + 1; i < right; ++i) {
ans[left][right] = Math.max(ans[left][right], solve(left, i) + solve(i, right) + val[left] * val[i] * val[right]);
}
return ans[left][right];
}
}
解法二:动态规划
理解官方题解并实现了第一种解法后,修改其形式。记忆化搜索的方式在求解高阶问题的过程中递归地求解低阶问题,用数组保存低阶问题的解,因此完全可以修改成动态规划的形式,先求解区间小的低阶问题,再求解高阶问题。
class Solution {
// ans[left][right]表示开区间(i, j)内的气球都填满后得到的最大硬币数
private int[][] ans;
// val[i]表示第i个位置上的值, 左右边界均为1
private int[] val;
public int maxCoins(int[] nums) {
int n = nums.length;
val = new int[n + 2];
for (int i = 0; i < n; ++i) {
val[i + 1] = nums[i];
}
val[0] = val[n + 1] = 1;
ans = new int[n + 2][n + 2];
for (int len = 2; len <= n + 1; ++len) {
for (int left = 0, right = left + len; right <= n + 1; ++left, ++right) {
for (int mid = left + 1; mid < right; ++mid) {
ans[left][right] = Math.max(ans[left][right], ans[left][mid] + ans[mid][right] + val[left] * val[mid] * val[right]);
}
}
}
return ans[0][n + 1];
}
}