戳气球 动态规划
1. 题目描述
有n
个气球,编号为0
到n-1
,每个气球上都标有一个数字,这些数字存在数组nums
中。
现在要求你戳破所有的气球。如果你戳破气球i
,就可以获得nums[left] * nums[i] * nums[right]
个硬币。 这里的left
和right
代表和i
相邻的两个气球的序号。注意当你戳破了气球i
后,气球left
和气球right
就变成了相邻的气球。
求所能获得硬币的最大数量。
示例:
输入: [3,1,5,8]
输出: 167
解释: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167
2. 题解
class Solution {
public int[][] rec;
public int[] val;
public int maxCoins(int[] nums) {
int n = nums.length;
val = new int[n + 2];
for (int i = 1; i <= n; i++) {
val[i] = nums[i - 1];
}
val[0] = val[n + 1] = 1;
rec = new int[n + 2][n + 2];
for (int i = 0; i <= n + 1; i++) {
Arrays.fill(rec[i], -1);
}
return solve(0, n + 1);
}
public int solve(int left, int right) {
if (left >= right - 1) {
return 0;
}
if (rec[left][right] != -1) {
return rec[left][right];
}
for (int i = left + 1; i < right; i++) {
int sum = val[left] * val[i] * val[right];
sum += solve(left, i) + solve(i, right);
rec[left][right] = Math.max(rec[left][right], sum);
}
return rec[left][right];
}
}
假设只有一个气球,气球上的数字为8
,那么所能获得硬币的最大数量为8
。
如果有两个气球[3,8]
,有两种情况:
1、先戳8
,后戳3
。所能获得硬币为3*8*1 + 1*3*1 = 27
。
2、先戳3
,后戳8
。所能获得硬币为1*3*8 + 1*8*1 = 32
。
因此,所能获得硬币的最大数量为32
。
LeetCode官方的题解说,戳气球会导致两个气球从不相邻变成相邻,使得后续操作难以处理。
倒过来看这些操作,先戳8
后戳3
,相当于先加3
,后加8
。
public int solve(int left, int right) {
if (left >= right - 1) { // 如果区间内无法添加气球,获得的硬币数就为0。比如区间[0,1]
return 0;
}
if (rec[left][right] != -1) {
return rec[left][right];
}
for (int i = left + 1; i < right; i++) {
int sum = val[left] * val[i] * val[right]; // 添加每个气球获得的硬币数
sum += solve(left, i) + solve(i, right); // 递归添加气球
rec[left][right] = Math.max(rec[left][right], sum);
}
return rec[left][right];
}
方法solve
里面的for
循环按顺序遍历数组中的每个元素,表示每个气球都有可能是第一个添加的。添加完第一个气球,剩余的气球都有可能是第二个添加的气球,以此类推,直到将所有气球添加到区间内刚好填满区间。
for
循环第二次遍历只是考虑将另一个气球作为第一个添加的气球。
如果有三个气球[3,5,8]
,有六种情况:
358:1*3*5 + 1*5*8 + 1*8*1 = 63
385:1*3*5 + 5*8*1 + 1*5*1 = 60
538:3*5*8 + 1*3*8 + 1*8*1 = 152
583:3*5*8 + 3*8*1 + 1*3*1 = 147
853:5*8*1 + 3*5*1 + 1*3*1 = 58
835:5*8*1 + 1*3*5 + 1*5*1 = 60
这里的358:
表示先戳3
,再戳5
,最后戳8
,相当于先加8
,再加5
,最后加3
。
如果有n个气球,就有n!
种情况,这属于组合问题。
参考: