【LeetCode】97. 交错字符串

1 问题

给定三个字符串 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 连接。

示例 1:

在这里插入图片描述
输入:s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
输出:true

示例 2:

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

示例 3:

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

2 答案

自己写的不对,回溯算法

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        # 从s3中逐个删除s1 s2,如果能删干净,则为true
        def dfs(s1, s2, s3, s1_True):
            if not s3:
                res.append(True)
                return
            if s1_True == True:
                for i in range(1, len(s1)+1):
                    if s1[:i] == s3[:i]:
                        s1 = s1[:i]
                        s3 = s3[:i]
                        dfs(s1, s2, s3, False)
            else:
                for i in range(1, len(s2)+1):
                    if s2[:i] == s3[:i]:
                        s2 = s2[:i]
                        s3 = s3[:i]
                        dfs(s1, s2, s3, True)
        res = []
        dfs(s1, s2, s3, True)
        return res[0]

再次尝试,用dfs,但是也不对,这样会在s1和s2相同的情况下,先走s1

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        if not s1 and not s2 and not s3:
            return True
        if s1 and s1[0] == s3[0]:
            return self.isInterleave(s1[1:], s2, s3[1:])
        elif s2 and s2[0] == s3[0]:
            return self.isInterleave(s1, s2[1:], s3[1:])
        return False

官方解,动态规划,感觉和机器人走路的题有点像
在这里插入图片描述
我们使用 d p [ i ] [ j ] dp[i][j] dp[i][j]表示 s 1 s_{1} s1 的前 i i i 个字符和 s 2 s_{2} s2 的前 j j j 个字符是否能构成 s 3 s_{3} s3 的前 i + j i+j i+j 个字符。 首先, d p [ 0 ] [ 0 ] dp[0][0] dp[0][0] 一定是 T r u e True True

  1. 初始化 s 1 , s 2 , s 3 s1,s2,s3 s1,s2,s3 的长度分别为 l e n 1 , l e n 2 , l e n 3 len1,len2,len3 len1,len2,len3
  2. l e n 1 + l e n 2 ! = l e n 3 len1+len2!=len3 len1+len2!=len3,表示一定不能构成交错字符串,返回 F a l s e False False
  3. 初始化 d p dp dp ( l e n 1 + 1 ) ∗ ( l e n 2 + 1 ) (len1+1)*(len2+1) (len1+1)(len2+1) F a l s e False False 数组。
  4. 初始化第一列 d p [ i ] [ 0 dp[i][0 dp[i][0,遍历第一列,遍历区间 [ 1 , l e n 1 + 1 ) [1,len1+1) [1,len1+1)
  • d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] a n d s 1 [ i − 1 ] = = s 3 [ i − 1 ] dp[i][0]=dp[i−1][0]ands1[i−1]==s3[i−1] dp[i][0]=dp[i1][0]ands1[i1]==s3[i1]。表示 s 1 s1 s1 的前 i i i 位是否能构成 s 3 s3 s3 的前 i i i 位。因此需要满足的条件为,前 i − 1 i-1 i1 位可以构成 s 3 s3 s3 的前 i − 1 i-1 i1 位且 s 1 s1 s1 的第 i i i 位( s 1 [ i − 1 ] s1[i-1] s1[i1])等于 s 3 s3 s3 的第 i i i 位( s 3 [ i − 1 ] s3[i-1] s3[i1]
  1. 初始化第一行 d p [ 0 ] [ j ] dp[0][j] dp[0][j],遍历第一行,遍历区间 [ 1 , l e n 2 + 1 ) [1,len2+1) [1,len2+1)
  • d p [ 0 ] [ i ] = d p [ 0 ] [ i − 1 ] a n d s 2 [ i − 1 ] = = s 3 [ i − 1 ] dp[0][i]=dp[0][i−1]ands2[i−1]==s3[i−1] dp[0][i]=dp[0][i1]ands2[i1]==s3[i1]。表示 s 2 s2 s2 的前 i i i 位是否能构成 s 3 s3 s3 的前 i i i 位。因此需要满足的条件为,前 i − 1 i-1 i1 位可以构成 s 3 s3 s3 的前 i − 1 i-1 i1 位且 s 2 s2 s2 的第 i i i 位( s 2 [ i − 1 ] s2[i-1] s2[i1])等于 s 3 s3 s3 的第 i i i 位( s 3 [ i − 1 ] s3[i-1] s3[i1]
  1. 遍历 d p dp dp 数组,每一行 i i i,遍历区间 [ 1 , l e n 1 + 1 ) [1,len1+1) [1,len1+1)
  • 每一列 j j j,遍历区间 [ 1 , l e n 2 + 1 ) [1,len2+1) [1,len2+1)
  • d p [ i ] [ j ] = ( d p [ i ] [ j − 1 ]   a n d   s 2 [ j − 1 ] = = s 3 [ i + j − 1 ] )   o r   ( d p [ i − 1 ] [ j ]   a n d   s 1 [ i − 1 ] = = s 3 [ i + j − 1 ] ) dp[i][j]=(dp[i][j-1]\ and\ s2[j-1]==s3[i+j-1])\ or\ (dp[i-1][j]\ and\ s1[i-1]==s3[i+j-1]) dp[i][j]=(dp[i][j1] and s2[j1]==s3[i+j1]) or (dp[i1][j] and s1[i1]==s3[i+j1])。解释: s 1 s1 s1 i i i 位和 s 2 s2 s2 的前 j j j 位能否组成 s 3 s3 s3 的前 i + j i+j i+j 位取决于两种情况:
  • s 1 s1 s1 的前 i − 1 i-1 i1 个字符和 s 2 s2 s2 的前 j j j 个字符能否构成 s 3 s3 s3 的前 i + j − 1 i+j-1 i+j1 位,且 s 1 s1 s1 的第 i i i 位( s 1 [ i − 1 ] s1[i-1] s1[i1])是否等于 s 3 s3 s3 的第 i + j i+j i+j 位( s 3 [ i + j − 1 ] s3[i+j-1] s3[i+j1])。
  • s 1 s1 s1 的前 i i i 个字符和 s 2 s2 s2 的前 j − 1 j-1 j1 个字符能否构成 s 3 s3 s3 的前 i + j − 1 i+j-1 i+j1 位,且 s 2 s2 s2 的第 j j j 位( s 2 [ j − 1 ] s2[j-1] s2[j1])是否等于 s 3 s3 s3 的第 i + j i+j i+j 位( s 3 [ i + j − 1 ] s3[i+j-1] s3[i+j1])。
  1. 返回 d p [ − 1 ] [ − 1 ] dp[-1][-1] dp[1][1]
class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        len1 = len(s1)
        len2 = len(s2)
        len3 = len(s3)
        if len1+len2 != len3:
            return False
        dp = [[False]*(len2+1) for i in range(len1+1)]
        dp[0][0] = True
        for i in range(1, len1+1):
            dp[i][0] = (dp[i-1][0] and s1[i-1] == s3[i-1])
        for j in range(1, len2+1):
            dp[0][j] = (dp[0][j-1] and s2[j-1] == s3[j-1]) 
        for i in range(1, len1+1):
            for j in range(1, len2+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])
        return dp[-1][-1]

https://leetcode.cn/problems/interleaving-string/solutions/48146/dong-tai-gui-hua-zhu-xing-jie-shi-python3-by-zhu-3/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouHerGetUp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值