Skip to content

Leetcode 1000. Minimum Cost to Merge Stones #234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Woodyiiiiiii opened this issue Apr 6, 2023 · 0 comments
Open

Leetcode 1000. Minimum Cost to Merge Stones #234

Woodyiiiiiii opened this issue Apr 6, 2023 · 0 comments

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented Apr 6, 2023

这是一系列区间DP类型专题。

区间DP有别于一般的线性DP,记录的对象是区间。所以一般用二维数组记录(Java),数组范围不会很大。

参考资料:

一般有两种写法,记忆化搜索递推迭代搜索。要确立好递归入口递归边界条件递推公式

相似题目:


看完No.1039和No.375后,来看看No.516。

这道题同样可以用区间DP。迭代写法的区别是因为i是从i+1推导出来的,所以要倒序迭代。递归写法和迭代写法分别如下:

class Solution {
    int n;
    int[][] memo;

    public int longestPalindromeSubseq(String s) {
        n = s.length();
        memo = new int[n][n];
        for (int i = 0; i < n; i++) {
            Arrays.fill(memo[i], -1);
        }
        return dfs(s, 0, n - 1);
    }

    private int dfs(String s, int i, int j) {
        if (i == j) {
            return 1;
        } else if (i > j) {
            return 0;
        }
        if (memo[i][j] != -1) {
            return memo[i][j];
        }
        if (s.charAt(i) == s.charAt(j)) {
            memo[i][j] = 2 + dfs(s, i + 1, j - 1);
        } else {
            memo[i][j] = Math.max(dfs(s, i + 1, j), dfs(s, i, j - 1));
        }
        return memo[i][j];
    }
}
class Solution {
    int n;
    int[][] memo;

    public int longestPalindromeSubseq(String s) {
        n = s.length();
        memo = new int[n][n];
        for (int i = n - 1; i >= 0; --i) {
            memo[i][i] = 1;
            for (int j = i + 1; j < n; ++j) {
                if (s.charAt(i) == s.charAt(j)) {
                    memo[i][j] = memo[i + 1][j - 1] + 2;
                } else {
                    memo[i][j] = Math.max(memo[i + 1][j], memo[i][j - 1]);
                }
            }
        }
        return memo[0][n - 1];
    }
}

这样看来,区间DP应用于连续区间,从空间状态上来看是一个倒三角形,上大下小。

当然,这道题还有另一种思路。将字符串s反转,然后求反转后的字符串与s的最长公共子序列。

class Solution {
    public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n + 1][n + 1];
        String rev = new StringBuilder(s).reverse().toString();
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (s.charAt(i - 1) == rev.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j - 1], Math.max(dp[i][j - 1], dp[i - 1][j]));
                }
            }
        }
        return dp[n][n];
    }
}

No.1000。

这题难点在于多了变量k。这里就要引用三维数组。

class Solution {
    int[] stones;
    int[] sums;
    int n, k;
    int[][][] dp;

    public int mergeStones(int[] stones, int k) {
        this.stones = stones;
        this.n = stones.length;
        this.k = k;
        if ((n - 1) % (k - 1) != 0) {
            return -1;
        }
        sums = new int[n + 1];
        for (int i = 0; i < n; i++) {
            sums[i + 1] = sums[i] + stones[i];
        }
        dp = new int[n][n][k + 1];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                Arrays.fill(dp[i][j], -1);
            }
        }
        return dfs(0, n - 1, 1);
    }

    private int dfs(int i, int j, int p) {
        if (dp[i][j][p] != -1) {
            return dp[i][j][p];
        }
        if (p == 1) {
            return dp[i][j][p] = i == j ? 0 : dfs(i, j, k) + sums[j + 1] - sums[i];
        }
        int res = Integer.MAX_VALUE;
        for (int m = i; m < j; m += k - 1) {
            res = Math.min(res, dfs(i, m, 1) + dfs(m + 1, j, p - 1));
        }
        return dp[i][j][p] = res;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant