[算法]LeetCode每日一题--312. 戳气球(Java)

DailyChallenge

312. 戳气球

Hard20200719

题目描述

有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。

现在要求你戳破所有的气球。如果你戳破气球 i ,就可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。

求所能获得硬币的最大数量。

说明:

  • 你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。
  • 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
示例:

输入: [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

链接:https://leetcode-cn.com/problems/burst-balloons

Solution

解题思路

这道题应该是区间DP的一道题目,那就按照区间DP来分析就可以了。
区间DP就看acwing上面大雪菜的讲解。

闫式DP分析法流程:

  1. 状态表示:
    • dp[i][j]表示nums[i,j]的气球全部被戳破的集合
    • 属性值:Max,从[i,j]气球全部被戳破的最大***数量
  2. 状态计算:
    • 扩展数组,加上题中的nums[-1] = nums[n] = 1,这样计算动态规划新数组的[1,n]
    • 先戳破[i,k - 1][k + 1, j]的气球,最后戳破第k个气球。dp[i][j] = Math.max(dp[i][j], dp[i][k - 1] + dp[k + 1][j] + s[i - 1] * s[k] * s[j + 1]);
    • dp[i][k - 1] + dp[k + 1][j]表示[i,k - 1][k + 1, j]被戳破所获得的最大coins数,s[i - 1] * s[k] * s[j + 1]表示最后戳破第k个气球所获得coins数目。
    • k 遍历[i,i + len - 1],保存最大值。
  3. 初始化:
    • 全部初始化为0

代码

class Solution {
    public int maxCoins(int[] nums) {
        // dp[i][j]表示nums中i到j的气球全部被戳破的集合。
        // 属性:Max,气球全部被戳破的最大coins数量。
        // dp[i][j] : 先戳破[i, k - 1]和[k + 1, j]的气球,最后戳破第k个气球获得转移方程。
        int n = nums.length;
        if(n == 0) return 0;
        int[][] dp = new int[n + 3][n + 3];
        // dp数组初始化为0
        int[] s = new int [n + 2];
        s[0] = s[n + 1] = 1;
        for(int i = 1; i <= n; i++){
            s[i] = nums[i - 1];
        }
        // 一重循环区间长度
        // 二重循环遍历数组
        for(int len = 1; len <= n; len++){
            for(int i = 1; i + len - 1 <= n; i++){
                int j = i + len - 1;
                // `k` 遍历`[i,i + len - 1]`,保存最大值。
                for(int k = i; k <= j; k++){
                    //`dp[i][k - 1] + dp[k + 1][j]`表示`[i,k - 1]`与`[k + 1, j]`被戳破所获得的最大coins数,`s[i - 1] * s[k] * s[j + 1]`表示最后戳破第k个气球所获得coins数目。
                    dp[i][j] = Math.max(dp[i][j], 
                    dp[i][k - 1] + dp[k + 1][j] + s[i - 1] * s[k] * s[j + 1]);
                }
            }
        }
        return dp[1][n];

    }
}


  • 我的公众号:GitKid。 暂时每日分享LeetCode, 让你走在路上坐在车上也能看算法题,欢迎大家扫码关注。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值