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
- 初始化 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
- 若 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
- 初始化 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 数组。
- 初始化第一列 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[i−1][0]ands1[i−1]==s3[i−1]。表示 s 1 s1 s1 的前 i i i 位是否能构成 s 3 s3 s3 的前 i i i 位。因此需要满足的条件为,前 i − 1 i-1 i−1 位可以构成 s 3 s3 s3 的前 i − 1 i-1 i−1 位且 s 1 s1 s1 的第 i i i 位( s 1 [ i − 1 ] s1[i-1] s1[i−1])等于 s 3 s3 s3 的第 i i i 位( s 3 [ i − 1 ] s3[i-1] s3[i−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][i−1]ands2[i−1]==s3[i−1]。表示 s 2 s2 s2 的前 i i i 位是否能构成 s 3 s3 s3 的前 i i i 位。因此需要满足的条件为,前 i − 1 i-1 i−1 位可以构成 s 3 s3 s3 的前 i − 1 i-1 i−1 位且 s 2 s2 s2 的第 i i i 位( s 2 [ i − 1 ] s2[i-1] s2[i−1])等于 s 3 s3 s3 的第 i i i 位( s 3 [ i − 1 ] s3[i-1] s3[i−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][j−1] and s2[j−1]==s3[i+j−1]) or (dp[i−1][j] and s1[i−1]==s3[i+j−1])。解释: 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 i−1 个字符和 s 2 s2 s2 的前 j j j 个字符能否构成 s 3 s3 s3 的前 i + j − 1 i+j-1 i+j−1 位,且 s 1 s1 s1 的第 i i i 位( s 1 [ i − 1 ] s1[i-1] s1[i−1])是否等于 s 3 s3 s3 的第 i + j i+j i+j 位( s 3 [ i + j − 1 ] s3[i+j-1] s3[i+j−1])。
- s 1 s1 s1 的前 i i i 个字符和 s 2 s2 s2 的前 j − 1 j-1 j−1 个字符能否构成 s 3 s3 s3 的前 i + j − 1 i+j-1 i+j−1 位,且 s 2 s2 s2 的第 j j j 位( s 2 [ j − 1 ] s2[j-1] s2[j−1])是否等于 s 3 s3 s3 的第 i + j i+j i+j 位( s 3 [ i + j − 1 ] s3[i+j-1] s3[i+j−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/