LeetCode 312.戳气球

2023-03-14 17:52:44 浏览数 (1)

LeetCode 312.戳气球

>

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

>

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

>

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

> 编者注:请务必理解题意,题目的要求是返回 所有可能 中的 最大值,气球被戳爆后,在下一状态是不存在的,[2 3 1 4] -> [2 3 4]

动态规划 (容易理解)

推荐配合 郭郭老师 的 视频 理解动归的思路

代码语言:javascript复制
public int maxCoins(int[] nums) {
        int len = nums.length;
        int[] arr = new int[len   2];
        int[][] dp = new int[len   2][len   2];
        System.arraycopy(nums, 0, arr, 1, len);
        arr[0] = arr[len   1] = 1;

//        枚举右指针,从下往上填表
        for (int left = len - 1; left >= 0; left--) {
            for (int right = left   2; right <= len   1; right  ) {
//                枚举 (left, right) 间的每个位置,作为最后戳爆的气球
//                1 3 1 5 8 1
//                若 5 为最后一个 则结果为 1*5*1   (1 3 1 5) 和 (5 8 1) 两个情况的结果
//                因此状态转移方程为
//                dp[left][right] = dp[left][mid]   dp[mid][right]   currRs
//                因为 mid ∈ (left, right), 因此每次结果会不同,维护最大值
                for (int mid = left   1; mid < right; mid  ) {
                    int sum = arr[left] * arr[mid] * arr[right];
                    sum  = dp[left][mid]   dp[mid][right];
                    dp[left][right] = Math.max(dp[left][right], sum);
                }
            }
        }
        return dp[0][len   1];
    }

记忆化搜索

代码语言:javascript复制
public int maxCoins(int[] nums) {
        int len = nums.length;
//        设置哨兵
        int[] arr = new int[len   2];
        System.arraycopy(nums, 0, arr, 1, len);
        arr[0] = 1;
        arr[len   1] = 1;
        int[][] memo = new int[len   2][len   2];
        for (int[] row : memo) {
            Arrays.fill(row, -1);
        }
        return solve(arr, memo, 0, len   1);
    }

    private int solve(int[] arr, int[][] memo, int left, int right) {
//        确保至少有三个,即中间至少有一个元素
        if (left   1 >= right) {
            return 0;
        }
//        记忆化搜索
        if (memo[left][right] != -1) {
            return memo[left][right];
        }
        for (int i = left   1; i < right; i  ) {
            int sum = arr[left] * arr[i] * arr[right];
            sum  = solve(arr, memo, left, i)   solve(arr, memo, i, right);
            memo[left][right] = Math.max(memo[left][right], sum);
        }
        return memo[left][right];
    }

0 人点赞