Skip to main content

97.交错字符串

标签: dynamic-programming, string

难度: Medium

通过率: 41.02%

原题链接: https://leetcode.com/problems/interleaving-string/description/

题目描述

给定字符串 s1s_1s2s_2s3s_3,判断 s3s_3 是否由 s1s_1s2s_2 的交错组成。

字符串 sstt 的交错是一种配置,其中 sstt 被分割成分别的 nnmm 个子串,如下所示:

s=s1+s2++sns = s_1 + s_2 + \ldots + s_n
t=t1+t2++tmt = t_1 + t_2 + \ldots + t_m
nm1|n - m| \leq 1
交错方式为 s1+t1+s2+t2+s3+t3+s_1 + t_1 + s_2 + t_2 + s_3 + t_3 + \ldotst1+s1+t2+s2+t3+s3+t_1 + s_1 + t_2 + s_2 + t_3 + s_3 + \ldots

注意: a+ba + b 表示字符串 aabb 的拼接。

解题思路

这是一个经典的动态规划问题。设一个二维布尔数组 dp[i][j]dp[i][j] 表示字符串 s3s_3 的前 i+ji+j 个字符是否由 s1s_1 的前 ii 个字符和 s2s_2 的前 jj 个字符交错组成。我们需要确定 dp[m][n]dp[m][n]。主要思想如下:

  1. 如果 s1[i1]==s3[i+j1]s_1[i-1] == s_3[i+j-1]dp[i1][j]dp[i-1][j] 为真,那么 dp[i][j]dp[i][j] 为真,这意味着可以通过将 s1s_1 的前 i1i-1 个字符与 s2s_2 的前 jj 个字符加上 s1s_1i1i-1 个字符来构成 s3s_3 的前 i+ji+j 个字符。

  2. 如果 s2[j1]==s3[i+j1]s_2[j-1] == s_3[i+j-1]dp[i][j1]dp[i][j-1] 为真,那么 dp[i][j]dp[i][j] 为真,这意味着可以通过将 s1s_1 的前 ii 个字符与 s2s_2 的前 j1j-1 个字符加上 s2s_2 的第 j1j-1 个字符来构成 s3s_3 的前 i+ji+j 个字符。

初始条件为 dp[0][0]=texttruedp[0][0] = \\text{true},因为空串之间是互相交错的。

最终结果取决于 dp[s1.length()][s2.length()]dp[s1.length()][s2.length()] 的值。

代码实现

def isInterleave(s1, s2, s3):
# 如果长度不匹配,直接返回 False
if len(s1) + len(s2) != len(s3):
return False

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

# 空串之间肯定是交错的
dp[0][0] = True

# 处理 s1 边界情况
for i in range(1, len(s1) + 1):
dp[i][0] = dp[i - 1][0] and s1[i - 1] == s3[i - 1]

# 处理 s2 边界情况
for j in range(1, len(s2) + 1):
dp[0][j] = dp[0][j - 1] and s2[j - 1] == s3[j - 1]

# 填充 DP 表
for i in range(1, len(s1) + 1):
for j in range(1, len(s2) + 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]

复杂度分析

时间复杂度:O(mn)O(m \cdot n),其中 mmnn 分别是 s1s1s2s2 的长度。我们需要填写一个 m×nm \times n 的 DP 表。 空间复杂度:O(mn)O(m \cdot n),用于存储 DP 表。可以通过优化将其降低到 O(n)O(n)