代码随想录训练营第五十五天| LeetCode392.判断子序列、LeetCode115.不同的子序列

LeetCode392. 判断子序列

题目链接:392. 判断子序列
思路
  • 第一步,确定dp数组以及其下标的含义

    • dp 数组表示以 i- 1 结尾的字符串 s,和以 j - 1 结尾的字符串 t, 相同子序列的长度。
  • 第二步,确定递推公式(考虑两种情况)

    • 情况一:chs[i - 1] == cht[j - 1] 时,此时相同子序列的长度为
      d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 dp[i][j] = dp[i - 1][j - 1] + 1 dp[i][j]=dp[i1][j1]+1

    • 情况二:chs[i - 1] != cht[j - 1] 时,此时相同子序列的长度为
      d p [ i ] [ j ] = d p [ i ] [ j − 1 ] dp[i][j] = dp[i][j - 1] dp[i][j]=dp[i][j1]

  • 第三步,初始化

    • 通过对递推公式的观察,需要初始化 dp[i][0]dp[0][j]。其表示 s 为空或者 t 为空时,相同子序列的长度,所以 dp[i][0] == 0dp[0][j] == 0
  • 第四步,遍历顺序

    • dp[i][j] 的值都是依赖于 dp[i - 1][j - 1]dp[i][j - 1],所以,遍历顺序是从上往下,从左往右。
代码
class Solution {
    public boolean isSubsequence(String s, String t) {
        int lens = s.length();
        int lent = t.length();
        char[] chs = s.toCharArray();
        char[] cht = t.toCharArray();
        int[][] dp = new int[lens + 1][lent + 1];

        for (int i = 1; i < lens + 1; i++){
            for (int j = 1; j < lent + 1; j++){
                if (chs[i - 1] == cht[j - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }else {
                    dp[i][j] = dp[i][j - 1];
                }
            }
        }
        if (dp[lens][lent] == lens){
            return true;
        }
        return false;
    }
}

LeetCode115.不同子序列

题目链接:115.不同子序列
思路
  • 第一步,确定dp数组以及其下标的含义

    • dp[i][j] 表示以 i- 1 结尾的 s 子序列出现以 j - 1 结尾的 t 的个数。
  • 第二步,确定递推公式(分两种情况考虑)

    • 情况一: chs[i - 1] == cht[j - 1],此时 dp[i][j] 由两部分组成,即 dp[i - 1][j - 1]dp[i - 1][j]。其中 dp[i - 1][j - 1] 容易理解,表示不考虑当前字符串 s 和字符串 t 最后一位字符。dp[i - 1][j] 表示采用 chs[i - 1] 进行匹配。
      d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + d p [ i − 1 ] [ j ] dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] dp[i][j]=dp[i1][j1]+dp[i1][j]

    • 情况二:chs[i - 1] != cht[j - 1],此时不采用当前字符串 s 的最后一位字符匹配。
      d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j] = dp[i - 1][j] dp[i][j]=dp[i1][j]

  • 第三步,初始化

    • 从递推公式可以得出,需要初始化 dp[i][0]dp[0][j]dp[i][0] 表示以 i- 1 结尾的字符串 s 中出现空字符串的个数。dp[0][j] 表示空字符串,出现以 j - 1 结尾的字符串 t 的个数。
    • 所以,dp[i][0] == 1dp[0][j]== 0,其中,特殊的 dp[0][0] == 1
  • 第四步,遍历顺序

    • 从递推公式得出,遍历顺序应该从上往下,从左往右。
代码:
class Solution {
    public int numDistinct(String s, String t) {
        char[] chs = s.toCharArray();
        char[] cht = t.toCharArray();
        int[][] dp = new int[chs.length + 1][cht.length + 1];

        for (int i = 0; i < chs.length; i++){
            dp[i][0] = 1;
        }
        for (int j = 1;j < cht.length; j++){
            dp[0][j] = 0;
        }

        for (int i = 1; i < chs.length + 1; i++){
            for (int j = 1; j < cht.length + 1; j++){
                if (chs[i - 1] == cht[j - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                }else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[chs.length][cht.length];
    }
}

你可能感兴趣的:(算法,leetcode,算法,动态规划)