在问 · 算法题解

97. 交错字符串

题目描述

输入三个字符串 s1、s2、s3,判断 s3 能否由 s1 和 s2 交错拼成。能则返回 true,否则返回 false。

交错的意思:把 s1 切成若干非空小段,s2 也切成若干非空小段,两边段数相差不超过 1。然后从其中一方开始,轮流取一段接在后面。

等价地说,s3 是 s1 与 s2 的所有字符穿插合并而成,并且来自 s1 的字符保持它们在 s1 中的顺序,来自 s2 的也一样。

示例 1
输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出:true

解释:s1 切成 aa|bc|c,s2 切成 dbbc|a,轮流拼接得 aa+dbbc+bc+a+c,正好是 s3。

示例 2
输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出:false

解释:无论怎么切分都拼不出 s3。

示例 3
输入:s1 = "", s2 = "", s3 = ""
输出:true

解释:三个都是空串,视为可以拼成。

数据范围

  • 0 <= s1.length, s2.length <= 100
  • 0 <= s3.length <= 200
  • s1、s2、s3 只含小写英文字母。

进阶:能否只用 O(s2.length) 的额外空间?

解题思路

设 dp[i][j] 表示 s1 前 i 个字符和 s2 前 j 个字符能否交错组成 s3 前 i+j 个字符。s3 的第 i+j 个字符 s3[i+j-1] 要么来自 s1[i-1](则需 dp[i-1][j] 为真),要么来自 s2[j-1](则需 dp[i][j-1] 为真)。长度不等时直接返回 false。

为什么正确

按行从左到右填表,上方和左边的格都已算好。

复杂度分析

时间 O(mn),空间 O(mn)。

易错点

贪心地“能从 s1 取就从 s1 取”是错的:s1 和 s2 当前字符相同时,两条路都要试,所以需要 DP。不要忘记先检查长度。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        m, n = len(s1), len(s2)
        if m + n != len(s3):
            return False
        dp = [[False] * (n + 1) for _ in range(m + 1)]
        dp[0][0] = True
        for i in range(m + 1):
            for j in range(n + 1):
                k = i + j - 1
                if i > 0 and s1[i - 1] == s3[k] and dp[i - 1][j]:
                    dp[i][j] = True
                if j > 0 and s2[j - 1] == s3[k] and dp[i][j - 1]:
                    dp[i][j] = True
        return dp[m][n]

载入编辑器,自己跑一遍 →

动态规划 专题的其他题目

查看 动态规划 全部题目 →