交叉字符串的判定
1.问题描述
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = “aabcc”,
s2 = “dbbca”,
When s3 = “aadbbcbcac”, return true.
When s3 = “aadbbbaccc”, return false.
2.原始思路
运用递归算法,判断s1或s2当前字母与s3当前字母是否匹配,此时可分为三种情况:
- 若仅s1与s3当前字母匹配则将s1与s3的当前字母删去形成s1’与s3’从而形成新的子问题(s1’, s2, s3’);
- 若仅s2与s3当前字母匹配则将s2与s3的当前字母删去形成s1’与s3’从而形成新的子问题(s1, s2’, s3’);
- 若s1和s2当前字母均与s3当前字母匹配则分别解(s1’, s2, s3’)和(s1, s2’, s3’),并返回它们的或。
代码如下:
def isInterleave(s1, s2, s3):
"""
:type s1: str
:type s2: str
:type s3: str
:rtype: bool
"""
if not len(s3) == len(s1) + len(s2):
return False
if len(s1) != 0 and len(s2) != 0 and s1[0] == s2[0] and s1[0] == s3[0]:
if isInterleave(s1[1:], s2, s3[1:]):
return True
else:
return isInterleave(s1, s2[1:], s3[1:])
if len(s1) == 0:
return cmp(s2, s3) == 0;
elif s1[0] == s3[0]:
return isInterleave(s1[1:], s2, s3[1:])
if len(s2) == 0:
return cmp(s2, s3) == 0
elif s2[0] == s3[0]:
return isInterleave(s1, s2[1:], s3[1:])
此方法思路简单,实现容易,但是效率低下,对同一个子问题会出现重复计算的情况。这里我们可以通过动态规划表更高效的解决这个问题。
2.动态规划算法
python代码如下:
def isInterleave(s1, s2, s3):
"""
:type s1: str
:type s2: str
:type s3: str
:rtype: bool
"""
if not len(s3) == len(s1) + len(s2):
return False
table = [[False for i in range(len(s2) + 1)] for i in range(len(s1) + 1)]
for i in range(len(s1) + 1):
for j in range(len(s2) + 1):
if i == 0 and j == 0:
table[i][j] = True
elif i == 0:
table[i][j] = (table[i][j - 1] and s2[j - 1] == s3[i + j - 1])
elif j == 0:
table[i][j] = (table[i - 1][j] and s1[i - 1] == s3[i + j - 1])
else:
table[i][j] = (table[i][j - 1] and s2[j - 1] == s3[i + j - 1]) or (table[i - 1][j] and s1[i - 1] == s3[i + j - 1])
return table[-1][-1]
具体参考LeetCode上的解法: