LeetCode 940. 不同的子序列 II

题目描述

940. 不同的子序列 II

思路分析

解法一:DP + 最近贡献(推荐)

核心思路

  • total 表示当前不同子序列数量(含空串)。
  • 遍历字符 c,新总数为 total * 2,但要减去上次 c 贡献的数量避免重复。
  • last[c] 记录上一次处理 c 时的 total


复杂度分析

  • 时间复杂度:O(n),其中 n 表示字符串长度。
  • 空间复杂度:O(1),仅 26 个字母。
class Solution {
    private static final int MOD = 1_000_000_007;

    public int distinctSubseqII(String s) {
        long total = 1;
        long[] last = new long[26];

        for (int i = 0; i < s.length(); i++) {
            int idx = s.charAt(i) - 'a';
            long next = (total * 2 - last[idx]) % MOD;
            if (next < 0) {
                next += MOD;
            }
            last[idx] = total;
            total = next;
        }

        return (int) ((total - 1 + MOD) % MOD);
    }
}
func distinctSubseqII(s string) int {
	const mod int64 = 1_000_000_007
	total := int64(1)
	last := make([]int64, 26)

	for i := 0; i < len(s); i++ {
		idx := s[i] - 'a'
		next := (total*2 - last[idx]) % mod
		if next < 0 {
			next += mod
		}
		last[idx] = total
		total = next
	}

	ans := (total - 1 + mod) % mod
	return int(ans)
}

相似题目

题目 难度 考察点
115. 不同的子序列 困难 DP
392. 判断子序列 简单 DP
132. 分割回文串 II 困难 DP
1143. 最长公共子序列 中等 DP
516. 最长回文子序列 中等 DP
本文作者:
本文链接: https://hgnulb.github.io/blog/2025/29983138
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!