Day57~392.判断子序列、115.不同的子序列

32 阅读2分钟

摘要

本文主要介绍了LeetCode动态规划的几个题目,包括392.判断子序列、115.不同的子序列。这两道问题与编辑距离问题有关。

1、392.判断子序列

1.1 思路

解题思路

动规五部曲

  • dp数组以及下标的定义: dp[i][j]表示字符串s下标i结尾是否是字符串t下标j结尾的最长公共子序列的长度为dp[i][j]
  • 递推公式:

    • if(s.charAt(i)==t.charAt(j) dp[i][j] = dp[i-1][j-1]) + 1;
    • dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1])
  • dp数组初始化

  • 遍历顺序

  • 打印dp数组

1.2 代码

    public boolean isSubsequence(String s, String t) {
        int len1 = s.length();
        int len2 = t.length();
        int[][] dp = new int[len1+1][len2+1];
​
        for(int i=1; i<=len1; i++) {
            for(int j=1; j<=len2; 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-1][j], dp[i][j-1]);
                }
            }
        }
        return dp[len1][len2] == len1;
    }

2、115.不同的子序列 *

2.1 思路

  • 思路

    • 这道题目相对于72. 编辑距离,简单了不少,因为本题相当于只有删除操作,不用考虑替换增加之类的
  • 动规五部曲

    • 确定dp数组(dp table)以及下标的含义

      • dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为 dp[i][j]
    • 确定递推公式

      • s[i - 1] 与 t[j - 1]相等

        • 例如: s:bagg 和 t:bag

          • s[3] 和 t[2]是相同的,但是字符串s也可以不用s[3]来匹配,即用s[0]s[1]s[2]组成的bag
        • dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];

      • s[i - 1] 与 t[j - 1] 不相等

        • dp[i][j]只有一部分组成,不用s[i - 1]来匹配(就是模拟在s中删除这个元素),即:dp[i - 1][j]
        • dp[i][j] = dp[i - 1][j]
    • dp数组如何初始化

      • dp[i][0]表示:以i-1为结尾的s可以随便删除元素,出现空字符串的个数

        • dp[i][0]一定都是1
      • dp[0][j]:空字符串s可以随便删除元素,出现以j-1为结尾的字符串t的个数

        • dp[0][j]一定都是0
      • dp[0][0] 应该是1

    • 确定遍历顺序

      • 遍历的时候一定是从上到下,从左到右
    • 举例推导dp数组

      • 115.不同的子序列

2.2 代码

    public int numDistinct(String s, String t) {
        int len1 = s.length();
        int len2 = t.length();
        int[][] dp = new int[len1+1][len2+1];
        dp[0][0] = 1;
​
        for(int i=1; i<=len1; i++) {
            dp[i][0] = 1;
​
            for(int j=1; j<=len2; 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[len1][len2];
    }

参考资料

代码随想录-392.判断子序列

代码随想录-115.不同的子序列