LeetCode312、戳气球(难)

题目描述

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/

猜你喜欢

转载自blog.csdn.net/qq_44861675/article/details/115047085