多用双指针和动态规划
具体方法参考labuladong经典动态规划:最长公共子序列
方法一: 自底向下的递归(双指针)
class Solution(object): def longestCommonSubsequence(self, text1, text2): """ :type text1: str :type text2: str :rtype: int """ mome = dict() def dp(i, j): # base case if i == -1: return 0 if j == -1: return 0 # 已经存在备忘录中直接返回 if (i, j) in mome.keys(): return mome[(i, j)] else: # 都在, 那公共子序列+1 if text1[i] == text2[j]: mome[(i, j)] = 1 + dp(i-1, j-1) else: mome[(i, j)] = max( dp(i-1, j), # text1不在 dp(i, j-1) # text2不在 ) return mome[(i, j)] return dp(len(text1) - 1, len(text2) - 1)方法二: 自底向上的动态规划
class Solution(object): def longestCommonSubsequence(self, text1, text2): """ :type text1: str :type text2: str :rtype: int """ num1 = len(text1) num2 = len(text2) # shape of dp = (num1 + 1, num2 + 1) dp = [[0] * (num2 + 1) for _ in range(num1 + 1)] # base case for i in range(1, num1 + 1): for j in range(1, num2 + 1): # 两个text的当前字符都在公共子序列中 if text1[i - 1] == text2[j - 1]: dp[i][j] = dp[i-1][j-1] + 1 else: # 至少有一个不在公共子序列中(都不在的包含在里面, 这次text1中的元素不在, 下次text2中的元素不在这不就其了) dp[i][j] = max( dp[i-1][j], # text1的第i个元素不在公共子序列中 dp[i][j-1] # text2的第i个元素不在公共子序列中 ) return dp[num1][num2]方法一: 自顶向下的递归, 几乎和上一题一样
class Solution(object): def minDistance(self, word1, word2): """ :type word1: str :type word2: str :rtype: int """ # 备忘录 mome = dict() def dp(i, j): # base case if i == -1: return j + 1 if j == -1: return i + 1 if (i, j) in mome: return mome[(i, j)] else: if word1[i] == word2[j]: mome[(i,j)] = dp(i-1, j-1) # 跳过 else: mome[(i, j)] = min( dp(i - 1, j), # 删除 dp(i - 1, j - 1), # 替换 dp(i, j - 1) # 在i后面插入word2[j] ) + 1 return mome[(i, j)] return dp(len(word1) - 1, len(word2) - 1)方法二: 动态规划
class Solution(object): def minDistance(self, word1, word2): """ :type word1: str :type word2: str :rtype: int """ # 备忘录 n1 = len(word1) n2 = len(word2) dp = [[0] * (n2 + 1) for _ in range(n1 + 1)] # base case注意这个基础情况 for i in range(1, n1 + 1): dp[i][0] = i for j in range(1, n2 + 1): dp[0][j] = j for i in range(1, n1 + 1): for j in range(1, n2 + 1): if word1[i-1] == word2[j-1]: dp[i][j] = dp[i-1][j-1] # 跳过 else: dp[i][j] = min( dp[i-1][j-1], # 替换 dp[i][j-1], # 插入 dp[i-1][j] # 删除 ) + 1 # 记得操作了一次之后次数+1 return dp[-1][-1]具体方法参考求两个字符串的最长公共子串
class Solution(object): def lcs(self, str1, str2): n1 = len(str1) n2 = len(str2) dp = [[0] * (n2 + 1) for _ in range(n1 + 1)] max_len = 0 for i in range(1, n1 + 1): for j in range(1, n2 + 1): if str1[i-1] == str2[j-1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = 0 max_len = max(dp[i][j], max_len) return max_len