版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ghscarecrow/article/details/86606436
Given n
balloons, indexed from 0
to n-1
. Each balloon is painted with a number on it represented by array nums
. You are asked to burst all the balloons. If the you burst balloon i
you will get nums[left] * nums[i] * nums[right]
coins. Here left
and right
are adjacent indices of i
. After the burst, the left
and right
then becomes adjacent.
Find the maximum coins you can collect by bursting the balloons wisely.
Note:
- You may imagine
nums[-1] = nums[n] = 1
. They are not real therefore you can not burst them. - 0 ≤
n
≤ 500, 0 ≤nums[i]
≤ 100
Example:
Input:[3,1,5,8]
Output:167 Explanation:
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
思路:对于该题,我们可以逆向思考,也就是无论我们前面如何选择气球,最后选择的总是剩下的最后那一个气球,再将那个气球与两个1相乘。定义一函数res获取从0 -> n-1 下标序列气球的最大收益值,则收益可表示为:从中选取一个气球作为最后爆炸的气球i,则收益可表示为:res(0,i-1) + 1*nums[i] * i+ res(i + 1,n-1);并采用迭代的方式记录下最大值,并将每种序列的最大值均记录在二维数组中,避免重复计算.
具体实现代码如下:
class Solution {
public int maxCoins(int[] nums) {
int[][] dp = new int[nums.length][nums.length];
return maxCoins(nums,dp,0,nums.length - 1);
}
public int get(int[] nums,int i) {
if(i==-1 || i==nums.length) {
return 1;
}
return nums[i];
}
public int maxCoins(int[] nums,int[][] dp,int start,int end){
if(start > end) {
return 0;
}
if(dp[start][end] != 0) {
return dp[start][end];
}
int max = nums[start];
for(int i=start;i<=end;i++) {
int val = maxCoins(nums,dp,start,i - 1) +
get(nums,start - 1) * get(nums,i) * get(nums,end + 1) +
maxCoins(nums,dp,i + 1,end);
max = Math.max(max,val);
}
dp[start][end] = max;//记录
return max;
}
}
leetcode上beat 100 %的代码
class Solution {
/**
* TIme: O(n^3); Space: O(n^2)
* Imp points:
* 1. dp[i][j] = for k in i, j: max(dp[i][k-1] + dp[k+1][j] + nums[k]*nums[i-1]*nums[j+1])
*/
public int maxCoins(int[] nums) {
int[] balloons = new int[nums.length+2];
int n = 1;
balloons[0] = 1;
for (int num : nums) {
if (num > 0) {
balloons[n++] = num;
}
}
balloons[n++] = 1;
int[][] dp = new int[n][n];
return maxCoins(0, n-1, balloons, dp);
}
private int maxCoins(int left, int right, int[] balloons, int[][] dp){
if (right - left <= 1){
return 0;
}
int max = 0;
for (int k = left+1; k < right; k++){
int maxLeft = dp[left][k] > 0 ? dp[left][k] : maxCoins(left, k, balloons, dp);
int maxRight = dp[k][right] > 0 ? dp[k][right] : maxCoins(k, right, balloons, dp);
max = Math.max(max, maxLeft + maxRight + balloons[k]*balloons[left]*balloons[right]);
}
dp[left][right] = max;
return max;
}
}