返回
力扣题目剖析:程序员必刷之最长公共子序列
前端
2023-11-14 07:34:04
前言
在程序员的成长道路上,力扣是一座无法逾越的高峰。它汇集了大量经典算法和数据结构题目,是检验程序员基本功的试金石。其中,「最长公共子序列」更是必刷题目之一。这道题不仅考察了你的算法能力,还考验了你的字符串处理技巧。
题目
给你两个字符串text1
和text2
,请你找出这两个字符串的最长公共子序列。一个字符串的子序列是指从该字符串中删除任意数量字符(也可以不删除)后剩余的字符串。例如,字符串 "abc"
的子序列包括 "a"
、"b"
、"c"
、"ab"
、"ac"
、"bc"
和 "abc"
。
解题思路
求最长公共子序列可以使用动态规划算法。我们定义一个二维数组dp
,其中dp[i][j]
表示text1
的前i
个字符和text2
的前j
个字符的最长公共子序列长度。
动态规划算法的递推公式如下:
dp[i][j] = dp[i - 1][j - 1] + 1,如果 text1[i] == text2[j]
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]),如果 text1[i] != text2[j]
代码实现
Python:
def longest_common_subsequence(text1, text2):
m, n = len(text1), len(text2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
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]
Java:
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length(), n = text2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}
C++:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.size(), n = text2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; 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[m][n];
}
复杂度分析
时间复杂度:O(mn),其中m和n分别为text1
和text2
的长度。
空间复杂度:O(mn),其中m和n分别为text1
和text2
的长度。
结语
「最长公共子序列」是力扣题库中一道经典题目,掌握它将极大地提升你的算法和字符串处理能力。通过本文的详细解析和代码示例,相信你已经对这道题有了深刻的理解。在今后的编程生涯中,希望这篇文章能成为你解决类似问题的指南。
延伸阅读