LeetCode 115 & 392:不同子序列 / 判断子序列

LeetCode 115 & 392:不同子序列 / 判断子序列 ------ 联合题解 ✅

这两道题 名字像、状态像、但 DP 含义完全不同。

📌 题目列表

题号 题目 类型
392 判断子序列 判定问题
115 不同的子序列 计数问题

📖 内容概要

给定字符串 s 和 t:

  • 392:判断 s 是否是 t 的子序列
  • 115:统计 t 在 s 中作为子序列出现的次数

✅ 动态规划

✅ 子序列问题

✅ 面试高频


💡 统一 DP 定义

java 复制代码
dp[i][j] = 
    s 的前 i 个字符
    与 t 的前 j 个字符
    的某种关系

🔁 状态转移对比(核心)

题目 相等时 不相等时
392 dp[i-1][j-1] + 1 dp[i][j-1]
115 dp[i-1][j-1] + dp[i-1][j] dp[i-1][j]

✅ 115 只用上一行(i-1)

✅ 392 只用当前行(i)


✅ 392 题:判断子序列(判定)

思路

  • 匹配成功 → 同时前进
  • 不匹配 → 只前进 t

AC 代码(Java)

java 复制代码
class Solution {
    public boolean isSubsequence(String s, String t) {
        char[] ss = s.toCharArray();
        char[] tt = t.toCharArray();
        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 (ss[i - 1] == tt[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = dp[i][j - 1];
                }
            }
        }
        return dp[len1][len2] == len1;
    }
}

✅ 为什么没有 dp[i-1][j]

  • 不能跳过 s
  • 只能跳过 t

✅ 115 题:不同子序列(计数)

思路

  • 匹配成功:
    • 用当前字符
    • 不用当前字符
  • 匹配失败:
    • 只能不用当前字符

AC 代码(Java)

java 复制代码
class Solution {
    public int numDistinct(String s, String t) {
        char[] ss = s.toCharArray();
        char[] tt = t.toCharArray();
        int len1 = s.length();
        int len2 = t.length();
        int[][] dp = new int[len1 + 1][len2 + 1];

        // 初始化
        for (int i = 0; i <= len1; i++) {
            dp[i][0] = 1;
        }

        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                if (ss[i - 1] == tt[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
问题类型 判定 计数
相等时 长度 +1 两种方案相加
不相等时 继承左边 继承上一行
DP 来源 当前行 上一行

⏱️ 复杂度分析

指标 复杂度
时间复杂度 O(len1 × len2)
空间复杂度 O(len1 × len2)

✅ 一句话总结

392 是在"找一条路",115 是在"数所有路"。


📌 面试加分点(建议记住)

  • ✅ 为什么 115 不用 dp[i][j-1]?
  • ✅ 为什么 392 不用 dp[i-1][j]?
  • ✅ 初始化为什么 dp[i][0] = 1?
  • ✅ 如何用滚动数组优化空间?
相关推荐
圣保罗的大教堂11 分钟前
leetcode 453. 最小操作次数使数组元素相等 中等
leetcode
aichitang202425 分钟前
代数拓扑学与现代前沿视角
考研·算法·数学建模·ai·拓扑学·高考
二本咕咕-机械转码38 分钟前
FreeRTOS深入解析(一)_链表与并发保护——哨兵循环链表、排序键游标、临界区与关调度
单片机·算法·链表
-银雾鸢尾-1 小时前
两数之和-C++实现
c++·算法
j7~1 小时前
【动态规划算法专题】动态规划五部曲实战:泰波那契数、三步问题、最小花费爬楼梯
c++·算法·动态规划·数据结构与算法
倍利福猎头公司官方账号1 小时前
大企业HR如何向猎头公司清晰传达AI岗位的技术需求?
人工智能·算法·机器人·求职招聘·业界资讯
揽星河..2 小时前
【C++】类和对象
c++·算法
D e re k ZH2 小时前
C++ 并发、未定义行为与工程化难点(No 3)
数据结构·c++·算法·面试
释厄6233 小时前
同性线套娃律——圆面积必然=1+2+...+n 的求和·圆心不与 π 相关
java·人工智能·算法·1024程序员节
暴力求解3 小时前
C++ ---继承(二)
开发语言·c++·算法