力扣第115题-不同的子序列

239 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

前言

力扣第115题 不同的子序列 如下所示:

给定一个字符串 s ****和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)

示例 1:

输入: s = "rabbbit", t = "rabbit"
输出 : 3
解释:
如下图所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。
rabbbit
rabbbit
rabbbit

一、思路

我们首先要直到什么是 子序列

子序列 是指在字符串中删除(也可不删除)但不交换字符串相对位置后组成的新字符串。

举个例子,ab 的子序列就有如下四种可能:

  • ab
  • a
  • b
  • `` (空字符串)

所以这一题我们翻译一下就是:寻找到 s 的子序列中出现字符串 t 的个数

按照上面的意思岂不是可以使用递归来生成字符串 s 的所有子序列,然后在子序列中找到 t 出现的次数?然而使用递归的话会因为时间复杂度过高而超时。

所以在碰到字符串相关的题目不妨使用 动态规划 来解决。

动态规划 的步骤大致如下所示:

  1. 定义二维数组

我们假设 dp[i][j] 为:** s从下标 i 到末尾的子字符串的子序列中中 t 从下标 j 到末尾字符串出现的个数**

  1. 状态转移方程

先处理边界情况

  • j == n,此时 t[j:] 为空字符串,空字符串是任何字符串的子序列,故 dp[i][n] = 1,即二维数组最后一列为 1
  • i == m,且 j < n,此时 s[i:] 为空字符串,而 t[j:] 不为空字符串,故 dp[m][j] = 0
  • i < m 且 j < n 时:
    • s[i] == t[j],那么就考虑 s[i] 这个字符串是否参与匹配?如匹配则 dp[i][j] = dp[i+1][j+1]。如不参与匹配,则 dp[i][j] = dp[i+1][j] 综上 dp[i][j] = dp[i+1][j+1] + dp[i+1][j]
    • s[i] != t[j],只能将 s 的子字符串缩小,故 dp[i][j] = dp[i+1][j]

二、实现

实现代码

我们在填写二维表格时是从后向前填写的。因为子字符串的长度是由短到长的一个过程。

    public int numDistinct(String s, String t) {
        int m = s.length(), n = t.length();
        if (m < n) {
            return 0;
        }
        int[][] dp = new int[m + 1][n + 1];
        // 初始化最后一列
        for (int i = 0; i <= m; i++) {
            dp[i][n] = 1;
        }
        for (int i = m - 1; i >= 0; i--) {
            char sChar = s.charAt(i);
            for (int j = n - 1; j >= 0; j--) {
                char tChar = t.charAt(j);
                if (sChar == tChar) {
                    // s[i] 两种情况:参加匹配或不参加
                    dp[i][j] = dp[i + 1][j + 1] + dp[i + 1][j];
                } else {
                    // 将 s 子字符串长度缩小
                    dp[i][j] = dp[i + 1][j];
                }
            }
        }
        return dp[0][0];
    }

测试代码

public static void main(String[] args) {
    int ret = new Number115().numDistinct("rabbbit", "rabbit");
    System.out.println(ret);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~