LeetCode:97. Interleaving String - Python

97. 交错字符串

问题描述:

给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1s2 交错组成的。

示例 1:

输入: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
输出: true

示例 2:

输入: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbbaccc”
输出: false

问题分析:

这个题目类似于115. Distinct Subsequences 或者有共同的解法。

先理解一下题目,验证 s3 是否是由 s1s2 交错组成的,也就是说,s3 是不是有这两个字符串相互交织组成,而且这两个字符串各用 1 次,不是多次哦。

题目已经给了提示,动态规划方法,现在就分析一下,先找一下问题的最优子结构:

(1)最优子结构或者子问题,s3是不是由s1s2相互交织组成是一个大问题,s3[1, n-1]是不是由s1[1, m-1]s2,或者s1s2[1, m-1]相互交织组成,现在是不是从大问题中,一步一步向下找到子问题了?(假设字符串从1开始计算)

(2)设dp[i][j]表示s3[0:i+j]是否可以由s1[0:i]s2[0:j]交织组成,现在看看如何求得dp[i][j]的值?很显然,有两个路径可以到达这个位置,即,从dp[i-1][j]的位置,然后判断s1[i-1] == s3[i+j-1],也就是让s1[i-1]作为s3[0: i+j]最后一个字符。同理也可以从dp[i][j-1]开始判断。

所以动态方程式为:

dp[i][j] = (dp[i-1][j] and s1[i-1] == s3[i+j-1]) or (dp[i][j-1] and s2[j-1] == s3[i+j-1])

(3) 以 s1, s2, s3 = "aabcc", "dbbca", "aadbbcbcac" 为例,看看dp的变化图:
在这里插入图片描述
(图片来自官方解答,下面已经给出链接)

Python3实现:

# @Time   :2019/02/05
# @Author :LiuYinxing
# 动态规划


class Solution:
    def isInterleave(self, s1, s2, s3):
        """
        :type s1: str
        :type s2: str
        :type s3: str
        :rtype: bool
        """
        if len(s3) != len(s1) + len(s2):
            return False

        dp = [[None] * (len(s2) + 1) for _ in range(len(s1)+1)]  # 初始化dp

        for i in range(len(s1)+1):
            for j in range(len(s2)+1):
                if i == 0 and j == 0:
                    dp[i][j] = True
                elif i == 0:  # 计算上边界
                    dp[i][j] = dp[i][j-1] and s2[j-1] == s3[i+j-1]
                elif j == 0:  # 计算下边界
                    dp[i][j] = dp[i-1][j] and s1[i-1] == s3[i+j-1]
                else:  # 从两个方向向左下角计算
                    dp[i][j] = (dp[i-1][j] and s1[i-1] == s3[i+j-1]) or (dp[i][j-1] and s2[j-1] == s3[i+j-1])
        return dp[-1][-1]


if __name__ == '__main__':
    solu = Solution()
    s1, s2, s3 = "aabcc", "dbbca", "aadbbcbcac"
    print(solu.isInterleave(s1, s2, s3))

空间压缩:,从上面的图片不难看出,我们一行一行的计算,所有的计算都是相邻行的计算,所以我们可以把空间压缩到一维,只保留一行。代码如下:

# @Time   :2019/02/05
# @Author :LiuYinxing
# 动态规划


class Solution:
    def isInterleave(self, s1, s2, s3):
        """
        :type s1: str
        :type s2: str
        :type s3: str
        :rtype: bool
        """
        if len(s3) != len(s1) + len(s2):
            return False

        dp = [None] * (len(s2) + 1)  # 初始化dp

        for i in range(len(s1)+1):
            for j in range(len(s2)+1):
                if i == 0 and j == 0:
                    dp[j] = True
                elif i == 0:  # 计算上边界
                    dp[j] = dp[j-1] and s2[j-1] == s3[i+j-1]
                elif j == 0:  # 计算下边界
                    dp[j] = dp[j] and s1[i-1] == s3[i+j-1]
                else:  # 从两个方向向左下角计算
                    dp[j] = (dp[j] and s1[i-1] == s3[i+j-1]) or (dp[j-1] and s2[j-1] == s3[i+j-1])
        return dp[-1]


if __name__ == '__main__':
    solu = Solution()
    s1, s2, s3 = "aabcc", "dbbca", "aadbbcbcac"
    print(solu.isInterleave(s1, s2, s3))

声明: 总结学习,有问题或不当之处,可以批评指正哦,谢谢。

题目链接参考链接

猜你喜欢

转载自blog.csdn.net/XX_123_1_RJ/article/details/86766908