You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求为不同子序列计数问题的递归代码添加记忆化(缓存)实现

解决递归记忆化优化的问题

我明白你的困扰——原来的递归写法因为传递实际的子串sub,不仅效率低下,还很难直接加记忆化缓存。其实我们可以换一种状态定义思路,用双指针来表示当前的匹配进度,这样就能轻松实现记忆化,把指数级复杂度降到多项式级别。

原代码的问题分析

原函数check通过传递sub、i、length来追踪匹配状态,但sub这个字符串作为缓存键既占空间又冗余,而且length本质上就是t已经匹配的长度(相当于j指针)。我们完全不需要保存sub,只需要知道:当前处理到s的第i位,已经匹配到t的第j位,这样的状态对应的子序列数量就足够了。

带记忆化的递归解法(自顶向下DP)

这里用Python的functools.lru_cache来实现记忆化,把i和j作为缓存的键:

from functools import lru_cache

def numDistinct(self, s: str, t: str) -> int:
    n = len(s)
    m = len(t)
    if n < m:
        return 0
    
    @lru_cache(maxsize=None)
    def dp(i, j):
        # 基准情况1:已经完全匹配t的所有字符,找到1个有效子序列
        if j == m:
            return 1
        # 基准情况2:s遍历完了但t还没匹配完,没有有效子序列
        if i == n:
            return 0
        
        # 情况1:不选s[i],直接递归处理s的下一位
        result = dp(i + 1, j)
        
        # 情况2:如果s[i]和t[j]相等,可以选择选s[i],递归处理两者的下一位
        if s[i] == t[j]:
            result += dp(i + 1, j + 1)
        
        return result
    
    return dp(0, 0)

思路解释

  • dp(i, j)的含义是:从s[i:](s从第i位到末尾)中,匹配t[j:](t从第j位到末尾)的不同子序列数量。
  • 记忆化缓存会自动存储已经计算过的(i,j)组合的结果,避免重复计算相同状态。
  • 时间复杂度降到了O(n*m),空间复杂度也是O(n*m)(缓存的状态总数)。

自底向上的动态规划解法(可选)

如果你不想用递归,也可以用二维数组实现自底向上的动态规划,同样高效:

def numDistinct(self, s: str, t: str) -> int:
    n = len(s)
    m = len(t)
    if n < m:
        return 0
    
    # dp[i][j]表示s的前i个字符中,匹配t的前j个字符的子序列数量
    dp = [[0] * (m + 1) for _ in range(n + 1)]
    
    # 初始化:空字符串是任何字符串的子序列,所以所有dp[i][0] = 1
    for i in range(n + 1):
        dp[i][0] = 1
    
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            # 不选s的第i个字符(对应s[i-1]),继承上一行的结果
            dp[i][j] = dp[i-1][j]
            
            # 如果当前字符匹配,加上选这个字符的情况(来自上一行前一列的结果)
            if s[i-1] == t[j-1]:
                dp[i][j] += dp[i-1][j-1]
    
    return dp[n][m]

思路解释

  • 初始化dp[i][0] = 1是因为空字符串是任何字符串的子序列,数量为1。
  • 双层循环遍历每个字符,逐步填充dp数组,状态转移逻辑和递归版完全一致。

内容的提问来源于stack exchange,提问作者Sumeet Bisen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:52:41