LeetCode-312. 戳气球

题目来源

312. 戳气球

题目详情

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

现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。

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

示例 1:

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

输入: nums = [1,5]
输出: 10

提示:

  • n == nums.length
  • 1 <= n <= 500
  • 0 <= nums[i] <= 100

题解分析

  1. 本题的实现是使用动态规划的思想,因为题目的描述出现了最大数量等词眼,而且题目是数组的形式出现,非常符合动态规划题目的形态。
  2. 要用动态规划就要思考子问题是什么,这里肯定不是从前i个元素的角度思考问题,因为戳气球涉及到相邻元素的相互影响。
  3. 5. 最长回文子串题目类似,这里需要考虑不同长度的子数组作为子问题。我们可以设置假设 dp[i][j] 表示开区间 (i,j) 内你能拿到的最多金币,并假设(i, j)区间中气球只剩最后一个,编号为k(k两边的气球都被戳爆了)。
  4. 状态转移方程如下:\(dp[i][j] = max(dp[i][j], dp[i][k] + nums[i] * nums[k] * nums[j] + dp[k][j])\)
class Solution {
    public int maxCoins(int[] nums) {
        int n = nums.length;
        int[] ball = new int[n+2];
        ball[0] = 1;
        ball[n+1] = 1;
        System.arraycopy(nums, 0, ball, 1, n);
        int[][] dp = new int[n+2][n+2];
        for(int len = 3; len <= n + 2; len++){
            for(int i=0; i<= n + 2 - len; i++){
                int j = i+ len - 1;
                dp[i][j] = 0;
                for(int k=i+1; k<j; k++){
                    dp[i][j] = Math.max(dp[i][k] +dp[k][j] + ball[i] * ball[k] * ball[j], dp[i][j]);
                }
            }
        }
        return dp[0][n+1];
    }
}

结果展示

image

posted @ 2022-01-19 11:14  Garrett_Wale  阅读(63)  评论(0编辑  收藏  举报