Leetcode 115 不同的子序列

文章讲述了如何通过动态规划算法解决一个字符串问题,即计算给定字符串s中的子序列与目标字符串t出现次数,结果对1e9+7取模。通过定义dp数组并利用状态转移方程,最终实现时间复杂度为O(n^2)和空间复杂度也为O(n^2)的解决方案。

题意理解:

        给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数,结果需要对 109 + 7 取模。

        

        即此题可以理解为:从s中删除元素去构造t,有多少种方法

        或者也可以理解为:s中按顺序取t,有多少个

        则一定有s和t的最长公共子序列为t, 那么s中有多少个这样的最长公共子序列呢。

        这里采用动态规划思路来解题,则首先要明确dp数组的含义。

解题思路:

        (1)定义dp数组

        dp[i][j]表示s的第i个元素前有多少个t的第j个元素前子串。

        (2)初始化

        dp[i][0]表示s的第i个元素前有多少个空串,dp[i][0]=1

        dp[0][j]表示空串里有多少个t的字串,dp[0][j]=0

        特别的dp[0][0]=1

        (3)递推公式

        当且仅当:        s[i-1]==t[j-1]时

                此时有两种情况:

                dp[i][j]=使用这个可以匹配的字符+不适用这个可以匹配的,尝试下一个可以匹配的字符

                          =dp[i-1][j-1](使用是s[i-1])+dp[i-1][j](不使用s[i-1],继续下一字符匹配)

        否则:      dp[i][j]=(不是使用该字符匹配)dp[i][j-1]

        (4)遍历顺序:总是从上到下,从左到右

        (5)返回

            dp[s.size][t.size]

1.动态规划解题

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

2.分析

时间复杂度:O(n^2)

空间复杂度:O(n^2)

### LeetCode 最长公共子序列问题的解决方案 解决LeetCode上的最长公共子序列(LCS)问题通常采用动态规划方法。以下是详细的解答过程以及Python实现。 #### 动态规划的核心思路 定义一个二维数组 `dp`,其中 `dp[i][j]` 表示字符串 `text1[:i]` 和 `text2[:j]` 的最长公共子序列长度。状态转移方程可以表示为: - 如果 `text1[i-1] == text2[j-1]`,则有: \[ dp[i][j] = dp[i-1][j-1] + 1 \] - 否则,取两者中的最大值: \[ dp[i][j] = \max(dp[i-1][j], dp[i][j-1]) \] 初始条件为当任意一方为空串时,其公共子序列为零,即 `dp[0][j] = 0` 和 `dp[i][0] = 0` 对于所有的 \( i, j \geq 0 \)[^1]。 #### Python 实现代码 下面是基于上述逻辑的Python实现: ```python def longestCommonSubsequence(text1: str, text2: str) -> int: m, n = len(text1), len(text2) # 创建DP表并初始化 dp = [[0] * (n + 1) for _ in range(m + 1)] # 填充DP表 for i in range(1, m + 1): for j in range(1, n + 1): if text1[i - 1] == text2[j - 1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) return dp[m][n] ``` 此函数接受两个字符串作为输入参数,并返回它们之间的最长公共子序列的长度[^3]。 #### 示例运行 考虑以下测试用例及其解释: - 输入 `text1 = "abcde"` 和 `text2 = "ace"`,输出应为 `3`,因为最长公共子序列是 `"ace"`[^2]。 - 当两字符串完全相同时,例如 `text1 = "abc"` 和 `text2 = "abc"`,结果亦为其长度 `3`。 - 若无任何共同字符存在,则如例子三所示,返回值应当为 `0`[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值