1、题目描述:
给定两个字符串 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 。
解法一:
动态数组:
定义二维数组dp[i][j],dp[i][j]表示text1前[i]个数与text2的前[j]个数的最长公共子序列的长度
dp[i][0]与dp[0][j]的初始值均为0
如果text1[i - 1] == text2[j - 1],则dp[i][j] = dp[i - 1][j - 1] + 1
如果text1[i - 1] != text2[j - 1],则dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
空间复杂度 O(n * m), n,m为字符串的长度
def longestCommonSubsequence( text1: str, text2: str) :
text1_ls = list(text1) #将字符串转成list
text2_ls = list(text2)
if len(text1_ls) == 0 or text1_ls == None:
return 0
if len(text2_ls) == 0 or text2_ls == None:
return 0
#定义一个列数为text1_ls + 1,行数text2_ls + 1的二维数组
dp = [[0] * (len(text1_ls) + 1) for _ in range(len(text2_ls) + 1)]
# 遍历行数,
for i in range(1, len(text2_ls) + 1):
for j in range(1, len(text1_ls) + 1):
if text2_ls[i - 1] == text1_ls[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[len(text2_ls)][len(text1_ls)]
优化1:将dp定义为2行的二维数组,减小空间复杂度
def longestCommonSubsequence_dp1( text1: str, text2: str) :
text1_ls = list(text1)
text2_ls = list(text2)
if len(text1_ls) == 0 or text1_ls == None:
return 0
if len(text2_ls) == 0 or text2_ls == None:
return 0
dp = [[0] * (len(text1_ls) + 1) for _ in range(2)]
for i in range(1, len(text2_ls) + 1):
for j in range(1, len(text1_ls) + 1):
row = i % 2
prerow = (i - 1) % 2
if text2_ls[i - 1] == text1_ls[j - 1]:
dp[row][j] = dp[prerow][j - 1] + 1
else:
dp[row][j] = max(dp[prerow][j], dp[i % 2][j - 1 ])
return dp[len(text2_ls) % 2][len(text1_ls)]
优化2,将二维数组优化成一维数组,进一步降低空间复杂度
def longestCommonSubsequence_dp2( text1: str, text2: str) :
text1_ls = list(text1)
text2_ls = list(text2)
if len(text1_ls) == 0 or text1_ls == None:
return 0
if len(text2_ls) == 0 or text2_ls == None:
return 0
dp = [0] * (len(text1_ls) + 1)
for i in range(1, len(text2_ls) + 1):
cur = 0
for j in range(1, len(text1_ls) + 1):
leftTop = cur
cur = dp[j]
if text2_ls[i - 1] == text1_ls[j - 1]:
dp[j] = leftTop + 1
else:
dp[j] = max(dp[j], dp[j - 1 ])
return dp[len(text1_ls)]