Leetcode刷题(15) 双字符串的问题

Leetcode刷题(15) 双字符串的问题

多用双指针和动态规划

1143. 最长公共子序列

具体方法参考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]

72. 编辑距离

方法一: 自顶向下的递归, 几乎和上一题一样

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值