美文网首页
LeetCode #1143 #Lint79 #72 #115

LeetCode #1143 #Lint79 #72 #115

作者: 40巨盗 | 来源:发表于2018-08-26 20:23 被阅读0次

Part 3 – Two Sequences Dynamic Programming

这类题目是动态规划乃至全LeetCode题目当中最难的题目,4个主要元素完全不固定,递推量和递推式都要因题而异而且不好确定。但做多了还是有些许规律可循的,大部分是针对字符串处理的动态规划题目,理清s字符串第i个字符和p字符串第j个字符之间的关系即可。
1)确定递推量。res[i][j]表示第一个字符串前i个字符配上第二个字符串前j个字符的状态;
2)推导递推式。res[i][j]一般研究第i个字符和第j个字符的匹配关系;
3)计算初始条件。res[i][0]/res[0][i];
4)考虑存储历史信息的空间维度(可选)。一般就是一维空间,不可优化。

1143. Longest Common Subsequence

https://leetcode-cn.com/problems/longest-common-subsequence/

res[i][j]表示前i个字符配上前j个字符的LCS长度。递推式即循环体内容,比较容易理解。注意这里建了一个长度为(m+1)*(n+1)的二维数组,方便计算,最后返回res[m][n]即可。
代码如下:

class Solution:
    """
    @param A: A string
    @param B: A string
    @return: The length of longest common subsequence of A and B
    """
    def longestCommonSubsequence(self, A, B):
        m = len(A)
        n = len(B)
        res = [[0 for j in range(n + 1)] for i in range(m + 1)]
        for i in range(m):
            for j in range(n):
                if A[i] == B[j]:
                    res[i + 1][j + 1] = res[i][j] + 1
                else:
                    res[i + 1][j + 1] = max(res[i + 1][j], res[i][j + 1])
        return res[m][n]

Lint79. Longest Common Substring

https://www.lintcode.com/problem/longest-common-substring/description

res[i][j]表示前i个字符配上前j个字符的LCS’的长度(一定以第i个和第j个字符结尾的LCS’),结果max也需要一直更新。
代码如下:

class Solution:
    """
    @param A: A string
    @param B: A string
    @return: the length of the longest common substring.
    """
    def longestCommonSubstring(self, A, B):
        m = len(A)
        n = len(B)
        res = [[0 for j in range(n + 1)] for i in range(m + 1)]
        max_value = 0
        for i in range(m):
            for j in range(n):
                if A[i] == B[j]:
                    res[i + 1][j + 1] = res[i][j] + 1
                else:
                    res[i + 1][j + 1] = 0
                max_value = max(max_value, res[i + 1][j + 1])
        return max_value

72. Edit Distance

https://leetcode.com/problems/edit-distance/description/

res[i][j]表示word1的前i个字符配上word2的前j个字符最少要用几次编辑使得他们相等。优先使用二维空间稳定版,有能力再使用一维空间优化版。
代码如下:

class Solution:
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        m = len(word1)
        n = len(word2)
        res = [[0 for n in range(n + 1)] for i in range(m + 1)]
        for i in range(m + 1):
            res[i][0] = i
        for j in range(n + 1):
            res[0][j] = j
        for i in range(m):
            for j in range(n):
                if word1[i] == word2[j]:
                    res[i + 1][j + 1] = res[i][j]
                else:
                    res[i + 1][j + 1] = min(res[i + 1][j], res[i][j + 1], res[i][j]) + 1
        return res[m][n]
class Solution:
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        m = len(word1)
        n = len(word2)
        if m < n:
            return self.minDistance(word2, word1)
        res = list(range(n + 1))
        for i in range(m):
            newRes = [0] * (n + 1)
            newRes[0] = i + 1
            for j in range(n):
                if word1[i] == word2[j]:
                    newRes[j + 1] = res[j]
                else:
                    newRes[j + 1] = min(res[j], res[j + 1], newRes[j]) + 1
            res = newRes
        return res[n]

115. Distinct Subsequences

https://leetcode.com/problems/distinct-subsequences/description/

res[i][j]表示S的前i个字符和T的前j个字符有多少个可行的序列。假设S的第i个字符和T的第j个字符不相同,那么就意味着res[i][j]的值和res[i - 1][j]的值相同,前面该是多少还是多少,而第i个字符的加入也不会多出来任何可行结果。如果S的第i个字符和T的第j个字符相同,那么所有res[i - 1][j - 1]中满足的结果都会成为新的满足的序列,当然res[i - 1][j]的也仍是可行的结果。算法进行两层循环,时间复杂度为O(m * n),空间复杂度O(m)。优先使用稳定版,有能力再使用优化版。
代码如下:

class Solution:
    def numDistinct(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: int
        """
        m = len(s)
        n = len(t)
        res = [[0 for j in range(n + 1)] for i in range(m + 1)]
        for i in range(m + 1):
            res[i][0] = 1
        for i in range(m):
            for j in range(n):
                if s[i] == t[j]:
                    res[i + 1][j + 1] = res[i][j] + res[i][j + 1]
                else:
                    res[i + 1][j + 1] = res[i][j + 1]
        return res[m][n]

代码如下:

class Solution:
    def numDistinct(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: int
        """
        m = len(s)
        n = len(t)
        res = [0] * (n + 1)
        res[0] = 1
        for i in range(m):
            for j in range(n)[::-1]:
                res[j + 1] += res[j] if s[i] == t[j] else 0
        return res[n]

97. Interleaving String

https://leetcode.com/problems/interleaving-string/description/

res[i][j]表示用s1的前i个字符和s2的前j个字符能不能按照规则表示出前s3的前i+j个字符。优先使用稳定版,有能力再使用优化版。
代码如下:

class Solution:
    def isInterleave(self, s1, s2, s3):
        """
        :type s1: str
        :type s2: str
        :type s3: str
        :rtype: bool
        """
        m = len(s1)
        n = len(s2)
        if m + n != len(s3):
            return False
        res = [[False for j in range(n + 1)] for i in range(m + 1)]
        res[0][0] = True
        for i in range(m):
            res[i + 1][0] = res[i][0] and s1[i] == s3[i]
        for j in range(n):
            res[0][j + 1] = res[0][j] and s2[j] == s3[j]
        for i in range(m):
            for j in range(n):
                res[i + 1][j + 1] = res[i][j + 1] and s1[i] == s3[i + j + 1] or res[i + 1][j] and s2[j] == s3[i + j + 1]
        return res[m][n]
class Solution:
    def isInterleave(self, s1, s2, s3):
        """
        :type s1: str
        :type s2: str
        :type s3: str
        :rtype: bool
        """
        m = len(s1)
        n = len(s2)
        if m + n != len(s3):
            return False
        if m < n:
            return self.isInterleave(s2, s1, s3)
        res = [False] * (n + 1)
        res[0] = True
        for i in range(n):
            res[i + 1] = res[i] and s2[i] == s3[i]
        for i in range(m):
            res[0] = res[0] and s1[i] == s3[i]
            for j in range(n):
                res[j + 1] = res[j + 1] and s1[i] == s3[i + j + 1] or res[j] and s2[j] == s3[i + j + 1]
        return res[n]

相关文章

网友评论

      本文标题:LeetCode #1143 #Lint79 #72 #115

      本文链接:https://www.haomeiwen.com/subject/exmnvftx.html