当前位置:首页 > 编程笔记 > 正文
已解决

leetCode 1143.最长公共子序列 动态规划

来自网友在路上 165865提问 提问时间:2023-10-09 05:25:49阅读次数: 65

最佳答案 问答题库658位专家为你答疑解惑

1143. 最长公共子序列 - 力扣(LeetCode)

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3 。

示例 2:

输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。

示例 3:

输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。

 >>思路和分析

本题和 leetCode 718.最长重复子数组 区别在于这里不要求是连续的了,但是要有相对顺序,即:"ace" 是 "abcde" 的子序列 ,但是 "aec" 不是 "abcde" 的子序列

>>动规五部曲

1.确定dp数组(dp table)以及下标的含义

dp[i][j] : 长度为 [0,i-1] 字符串 text1 与长度为 [0,j-1]字符串text2最长公共子序列为dp[i][j]

2.确定递推公式

思考:有哪些方向可以推出dp[i][j]

  • text1[i-1] == text[j-1]时,dp[i][j]=dp[i-1][j-1]+1
  • text1[i-1] != text[j-1]时,分两种情况讨论:
    • 情况①: 不看e了,考虑c,就是abc和ac。这两个原字符串的最长公共子序列也可能是abc和ac的最长公共子序列。因为c和e明显不相同,那么可不考虑e了
    • 情况②: 同理,也可以不看c了,考虑e,就是ab和ace。这两个字符串也可能是两个原字符串的最长公共子序列
    • 那么这两种情况应该怎么取呢?这两种情况都有可能是dp[i][j],那么
      • dp[i][j] = max(dp[i][j-1],dp[i-1][j]);
        • 情况①对应dp[i][j-1]
        • 情况②对应dp[i-1][j]
确定递推公式:
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]);

3.dp数组初始化

  • dp[i][0] 应该初始化为0,因为 test1[0,i-1] 空串最长公共子序列是0
  • dp[0][j] 同理也为0
  • 其他下标都是随着递推公式逐步覆盖,初始为多少都可以

故统一初始为0,代码如下:

vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));

4.确定遍历顺序

那么为了在递推的过程中,这三个方向都是经过计算的数值,所以要从前向后从上到下来遍历这个矩阵

5.举例推导dp数组

由上图可看到dp[text1.size()][text2.size()]为最终结果

class Solution {
public:int longestCommonSubsequence(string text1, string text2) {vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));for (int i = 1; i <= text1.size(); i++) {for (int j = 1; j <= text2.size(); j++) {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[text1.size()][text2.size()];}
};
  • 时间复杂度: O(n * m),其中 n 和 m 分别为 text1 和 text2 的长度
  • 空间复杂度: O(n * m)

参考文章和视频:

动态规划子序列问题经典题目 | LeetCode:1143.最长公共子序列_哔哩哔哩_bilibili 代码随想录 (programmercarl.com)

来自代码随想录课堂截图:

 

查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"leetCode 1143.最长公共子序列 动态规划":http://eshow365.cn/6-17627-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!