给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。
示例 1:
输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出: true
示例 2:
输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出: false
解题思路
这个问题非常简单,我们首先想到的解法就是通过递归。我们定义 f ( s 1 , s 2 , s 3 ) f(s1,s2,s3) f(s1,s2,s3)返回我们最后的结果,那么我们可以分成如下四种情况考虑。
- s 1 [ 0 ] = s 3 [ 0 ] & s 2 [ 0 ] ≠ s 3 [ 0 ] s_1[0]=s_3[0]\ \& \ s_2[0]\neq s_3[0] s1[0]=s3[0] & s2[0]̸=s3[0]
- s 1 [ 0 ] ≠ s 3 [ 0 ] & s 2 [ 0 ] = s 3 [ 0 ] s_1[0]\neq s_3[0]\ \& \ s_2[0] = s_3[0] s1[0]̸=s3[0] & s2[0]=s3[0]
- s 1 [ 0 ] = s 3 [ 0 ] & s 2 [ 0 ] = s 3 [ 0 ] s_1[0]=s_3[0]\ \& \ s_2[0] = s_3[0] s1[0]=s3[0] & s2[0]=s3[0]
- s 1 [ 0 ] ≠ s 3 [ 0 ] & s 2 [ 0 ] ≠ s 3 [ 0 ] s_1[0]\neq s_3[0]\ \& \ s_2[0]\neq s_3[0] s1[0]̸=s3[0] & s2[0]̸=s3[0]
对于第一种情况,我们返回
f
(
s
1
[
1
:
]
,
s
2
,
s
3
[
1
:
]
)
f(s_1[1:],s_2,s_3[1:])
f(s1[1:],s2,s3[1:])。对于第二种情况,我们返回
f
(
s
1
,
s
2
[
1
:
]
,
s
3
[
1
:
]
)
f(s_1,s_2[1:],s_3[1:])
f(s1,s2[1:],s3[1:])。对于第三种情况,我们返回
f
(
s
1
[
1
:
]
,
s
2
,
s
3
[
1
:
]
)
∣
∣
f
(
s
1
,
s
2
[
1
:
]
,
s
3
[
1
:
]
)
f(s_1[1:],s_2,s_3[1:]) \ ||\ f(s_1,s_2[1:],s_3[1:])
f(s1[1:],s2,s3[1:]) ∣∣ f(s1,s2[1:],s3[1:])。对于第四种情况,我们返回False
。现在我们考虑边界问题。会分成两种情况
- s 1 s_1 s1为空, s 2 s_2 s2不为空
- s 2 s_2 s2为空, s 1 s_1 s1不为空
- s 1 s_1 s1为空, s 2 s_2 s2为空
对于第一种情况,我们首先要判断
s
2
[
0
]
=
=
s
3
[
0
]
s_2[0]==s_3[0]
s2[0]==s3[0],如果成立,我们返回
f
(
s
1
,
s
2
[
1
:
]
,
s
3
[
1
:
]
)
f(s_1,s_2[1:],s_3[1:])
f(s1,s2[1:],s3[1:]),否则我们返回False
。对于第二种情况,我们首先要判断
s
1
[
0
]
=
=
s
3
[
0
]
s_1[0]==s_3[0]
s1[0]==s3[0],如果成立,我们返回
f
(
s
1
[
1
:
]
,
s
2
,
s
3
[
1
:
]
)
f(s_1[1:],s_2,s_3[1:])
f(s1[1:],s2,s3[1:]),否则我们返回False
。对于第三种情况,我们返回True
。
class Solution:
def isInterleave(self, s1, s2, s3):
"""
:type s1: str
:type s2: str
:type s3: str
:rtype: bool
"""
if len(s1) + len(s2) != len(s3):
return False
if not s1 and not s2:
return True
elif not s1:
return self.isInterleave(s1, s2[1:], s3[1:]) and s2[0] == s3[0]
elif not s2:
return self.isInterleave(s1[1:], s2, s3[1:]) and s1[0] == s3[0]
if s1[0] == s3[0] and s2[0] != s3[0]:
return self.isInterleave(s1[1:], s2, s3[1:])
elif s2[0] == s3[0] and s1[0] != s3[0]:
return self.isInterleave(s1, s2[1:], s3[1:])
elif s1[0] == s3[0] and s2[0] == s3[0]:
return self.isInterleave(s1[1:], s2, s3[1:]) or self.isInterleave(s1, s2[1:], s3[1:])
else:
return False
我们同样可以使用记忆化搜索优化这个问题,这里我就不再赘述了。我们还可以使用另一种思路,我们将之前定义的函数 f ( s 1 , s 2 , s 3 ) f(s_1,s_2,s_3) f(s1,s2,s3)就需要做一些调整,我们现在定义一个新的 f ( i , j ) f(i,j) f(i,j),其中 i i i和 j j j表示输入 s 1 s_1 s1和 s 2 s_2 s2的位置。我们依旧会考虑四种情况
- i = 0 & j ≠ 0 i=0\ \& \ j\neq 0 i=0 & j̸=0
- i ≠ 0 & j = 0 i \neq 0\ \& \ j = 0 i̸=0 & j=0
- i = 0 & j = 0 i=0\ \& \ j = 0 i=0 & j=0
- i ≠ 0 & j ≠ 0 i\neq 0\ \& \ j\neq 0 i̸=0 & j̸=0
对于第一种情况,我们返回
f
(
i
,
j
−
1
)
&
s
2
[
j
−
1
]
=
=
s
3
[
i
+
j
−
1
]
f(i,j-1)\ \& \ s_2[j-1]==s_3[i+j-1]
f(i,j−1) & s2[j−1]==s3[i+j−1]。对于第二种情况,我们返回
f
(
i
−
1
,
j
)
&
s
1
[
i
−
1
]
=
=
s
3
[
i
+
j
−
1
]
f(i-1,j)\ \& \ s_1[i-1]==s_3[i+j-1]
f(i−1,j) & s1[i−1]==s3[i+j−1]。对于第三种情况,我们返回True
。对于第四种情况,我们返回
(
f
(
i
−
1
,
j
)
&
s
1
[
j
−
1
]
=
=
s
3
[
i
+
j
−
1
]
)
∣
∣
f
(
i
,
j
−
1
)
&
s
2
[
j
−
1
]
=
=
s
3
[
i
+
j
−
1
]
(f(i-1,j)\ \& \ s_1[j-1]==s_3[i+j-1])\ || \ f(i,j-1)\ \& \ s_2[j-1]==s_3[i+j-1]
(f(i−1,j) & s1[j−1]==s3[i+j−1]) ∣∣ f(i,j−1) & s2[j−1]==s3[i+j−1]。
class Solution:
def isInterleave(self, s1, s2, s3):
"""
:type s1: str
:type s2: str
:type s3: str
:rtype: bool
"""
s1_len, s2_len, s3_len = len(s1), len(s2), len(s3)
if s1_len + s2_len != s3_len:
return False
return self._isInterleave(s1_len, s2_len, s1, s2, s3)
def _isInterleave(self, i, j, s1, s2, s3):
if i == 0 and j == 0:
return True
elif i == 0:
return self._isInterleave(i, j - 1, s1, s2, s3) and (s2[j - 1] == s3[i + j - 1])
elif j == 0:
return self._isInterleave(i - 1, j, s1, s2, s3) and (s1[i - 1] == s3[i + j - 1])
else:
return (self._isInterleave(i, j - 1, s1, s2, s3) and (s2[j - 1] == s3[i + j - 1])) or \
(self._isInterleave(i - 1, j, s1, s2, s3) and (s1[i - 1] == s3[i + j - 1]))
这种做法比前面的算法好的地方在于我们可以快速的通过动态规划去优化它。
class Solution:
def isInterleave(self, s1, s2, s3):
"""
:type s1: str
:type s2: str
:type s3: str
:rtype: bool
"""
s1_len, s2_len, s3_len = len(s1), len(s2), len(s3)
if s1_len + s2_len != s3_len:
return False
mem = [[False]*(s2_len + 1) for _ in range(s1_len + 1)]
for i in range(s1_len + 1):
for j in range(s2_len + 1):
if i == 0 and j == 0:
mem[i][j] = True
elif i == 0:
mem[i][j] = mem[i][j - 1] and (s2[j - 1] == s3[i + j - 1])
elif j == 0:
mem[i][j] = mem[i - 1][j] and (s1[i - 1] == s3[i + j - 1])
else:
mem[i][j] = (mem[i][j-1] and (s2[j - 1] == s3[i + j - 1])) or \
(mem[i - 1][j] and (s1[i - 1] == s3[i + j - 1]))
return mem[-1][-1]
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!