代码随想录-2023/08/26

113 阅读2分钟

动态规划

392.判断子序列

解题思路:

类似于这种两个字符串比较,替换,删除的题目都可以用二维dp解决

  1. 定义dp数组含义: dp[i][j]代表si-1结尾, mj-1结尾的最长公共子序列
  2. 初始化: 当word1为空时, 两个字符串相同的最少操作次数是word2的长度, 即删除所有的word2
  3. 双重for循环比较:
  • 两个字符相等时: 最长公共子序列长度就是dp[i-1[j-1] + 1
  • 当不相等时: 最长公共子序列长度 = Math.max(dp[i-1][j], dp[i][j-1])
  1. 最后判断最长公共子序列长度是否等于s的长度即可

代码:

class Solution {
    // 判断子序列本质: 找最长公共子序列长度是否等于子序列长度
    public boolean isSubsequence(String s, String t) {
        int m = s.length(), n = t.length();
        // 动态规划---找最长公共子序列
        int[][] dp = new int[m+1][n+1];
        for(int i=1; i<=m; i++){
            for(int j=1; j<=n; j++){
                if(s.charAt(i-1) == t.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else{
                    dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
                }
            }
        }
        // 若最长公共子序列长度 = m, 则代表s是t的子序列
        return dp[m][n] == m;
    }
}

115.不同的子序列

解题思路:二维dp

  1. 定义dp数组含义: si-1结尾, tj-1结尾的s的子序列中t出现的个数
  2. 若两个字符相等: 则当前dp[i][j] 可以使用当前元素来匹配, 或者不使用当前元素来匹配
  3. 若两个字符不相等: 则不能使用当前元素来匹配

代码:

class Solution {
    // 动态规划
    public int numDistinct(String s, String t) {
        int m = s.length(), n = t.length();
        // dp 数组含义: 定义s以i结尾, t以j结尾的s中t的不同子序列个数
        int[][] dp = new  int[m+1][n+1];
        // 初始化
        for (int i = 0; i <= m; i++) dp[i][0] = 1;
        for(int i=1; i<=m; i++){
            for(int j=1; j<=n; j++){
                if(s.charAt(i-1) == t.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
                }else{
                    dp[i][j] = dp[i-1][j];
                }
            }
        }
        return dp[m][n];
    }
}