题目描述
https://leetcode-cn.com/problems/burst-balloons/
解法(动规)
看了大概7、8分钟,没有思路。自己暴力的想法是n的阶乘级别,代码也难写。直接看题解,很巧妙,很惊叹。
参考讲解:经典动态规划:戳气球
直接上代码:
class Solution {
public int maxCoins(int[] nums) {
if(nums==null || nums.length==0) return 0;
if(nums.length==1) return nums[0];
//定义两个虚拟气球,拓展了nums的长度,防止了下标越界的处理麻烦
int [] new_nums = new int[nums.length+2];
new_nums[0] = new_nums[new_nums.length-1] = 1;
for(int i=1;i<=nums.length;i++){
new_nums[i] = nums[i-1];
}
//dp[i][j]表示搓破(i,j)之间的气球获得的最大硬币数量
//边界条件:dp[i][i] = 0,它们之间没有气球,dp[i][i= +1]=0;它们之间也没有气球
int[][]dp = new int[new_nums.length][new_nums.length];
//递推方程:找到可能最后搓破的k气球,使得得到的dp[i][j]为最大值
//dp[i][j] = dp[i][k] + dp[k][j]+ point[i]*point[k]*point[j]
//因为搓破了最后一个气球k则其相邻的气球为i和j。
//戳破k之前必须先戳破dp[i][k]和dp[k][j]
//确认遍历i和j的顺序,通过最终结果的位置和base case的位置以及要计算的递推方程确定。
//斜着遍历,或者i从大到小,j从小到大,
for(int i=nums.length;i>=0;i--){
for(int j=i+1;j<new_nums.length;j++){
for(int k=i+1;k<j;k++){//做选择
dp[i][j] = Math.max(dp[i][j],
dp[i][k] + dp[k][j]+ new_nums[i]*new_nums[k]*new_nums[j]);
}
}
}
return dp[0][nums.length+1];
}
}
时间复杂度应该为O(n3)
感悟:区间dp就是缩小搜索范围的一个过程。
模板总结参考:https://leetcode-cn.com/problems/burst-balloons/solution/yi-wen-tuan-mie-qu-jian-dp-by-bnrzzvnepe-2k7b/