​LeetCode刷题实战97:交错字符串

程序IT圈

共 537字,需浏览 2分钟

 ·

2020-11-18 01:44

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 交错字符串,我们先来看题面:

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

Given strings s1, s2, and s3, find whether s3 is formed by an interleaving of s1 and s2.


An interleaving of two strings s and t is a configuration where they are divided into non-empty substrings such that:


s = s1 + s2 + ... + sn

t = t1 + t2 + ... + tm

|n - m| <= 1

The interleaving is s1 + t1 + s2 + t2 + s3 + t3 + ... or t1 + s1 + t2 + s2 + t3 + s3 + ...

Note: a + b is the concatenation of strings a and b.

题意


给定三个字符串 s1、s2、s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。

两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:

s = s1 + s2 + ... + sn
t = t1 + t2 + ... + tm
|n - m| <= 1
交错 是 s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...
提示:a + b 意味着字符串 a 和 b 连接。

样例


解题

https://my.oschina.net/u/3640932/blog/4405751


动态规划

这个问题我们可以转换为求证,s3 是否能够从向下选取 s1,向右选取 s2,这样的形式,去求得是否存在 s3 这条路径。

状态定义

设 dp[i][j] 表示 s1 前 i 个字符和 s2 前 j 个字符能够拼接成 s3(i+j) 个字符,也就是当前路径存在。

状态转移方程

如果 s1 的第 i 个元素和 s3 的第 i+j 个元素相等,那么 dp[i][j] 是否成立,则需要看 dp[i-1][j] 是否成立,也就是这里需要看 s1 的前 i-1 个元素和 s2 的前 j 个元素能否拼接成 s3 的前 i+j-1 个元素。
同样的 如果 s2 的第 j 个元素和 s3 的第 i+j 个元素相等,此时 dp[i][j] 是否成立,则需要看 dp[i][j-1] 是否成立,也就是需要看 s2 的前 i 个元素和 s2 的前 j-1 个元素是否能够拼接成 s3 的前 i+j-1 个元素。
那么最终的状态转移方程为:
dp[i][j] = (dp[i-1][j] and s3[i+j-1]=s1[i-1]) or (dp[i][j-1] and s3[i+j-1]=s2[j-1])

状态初始化

  • dp[0][0] = True

  • 如果 j = 0, dp[i][0] 是否成立,取决于 dp[i-1][0] 以及 s1 的第 i 个字符是否等于 s3 的第 i 个字符;

  • 如果 i = 0, dp[0][j] 是否成立,取决于 dp[0][j-1] 以及 s3 的第 i 个字符与 s2 的第 i 个字符是否相等。

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        # 先处理特殊情况,如果 s1 和 s2 的长度和不等于 s3 的长度,则返回 False。因为无法交错拼接
        if len(s1) + len(s2) != len(s3):
            return False
        
        m = len(s1)
        n = len(s2)

        # 状态定义
        dp = [[False] * (n+1) for _ in range(m+1)]
        # 初始化
        dp[0][0] = True
        for i in range(1, m+1):
            dp[i][0] = dp[i-1][0] and s3[i-1] == s1[i-1]
        for j in range(1, n+1):
            dp[0][j] = dp[0][j-1] and s3[j-1] == s2[j-1]

        for i in range(1, m+1):
            for j in range(1, n+1):
                dp[i][j] = (dp[i-1][j] and s3[i+j-1]==s1[i-1]) or (dp[i][j-1] and s3[i+j-1]==s2[j-1])

        return dp[-1][-1]


好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力。


上期推文:

LeetCode50-80题汇总,速度收藏!
LeetCode刷题实战81:搜索旋转排序数组 II
LeetCode刷题实战82:删除排序链表中的重复元素 II
LeetCode刷题实战83:删除排序链表中的重复元素
LeetCode刷题实战84: 柱状图中最大的矩形
LeetCode刷题实战85:最大矩形
LeetCode刷题实战86:分隔链表
LeetCode刷题实战87:扰乱字符串
LeetCode刷题实战88:合并两个有序数组
LeetCode刷题实战89:格雷编码
LeetCode刷题实战90:子集 II
LeetCode刷题实战91:解码方法
LeetCode刷题实战92:反转链表 II
LeetCode刷题实战93:复原IP地址
LeetCode刷题实战94:二叉树的中序遍历
LeetCode刷题实战95:不同的二叉搜索树 II
LeetCode刷题实战96:不同的二叉搜索树

浏览 17
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报