版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jining11/article/details/83793919
题目要求
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
Example 1:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true
Example 2:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false
注意到interleaving的含义是交错,也就是说s1、s2在相互交错以连接为s3时,必须要保证其内部的字符是有序且不可跳过的。
极其简单的递归法
class Solution {
public:
bool find(string s1, string s2, string s3) {
if (s1+s2 == s3) {
return true;
}
if (s1[0] == s3[0] && find(s1.substr(1), s2, s3.substr(1))) {
return true;
}
if (s2[0] == s3[0] && find(s1, s2.substr(1), s3.substr(1))) {
return true;
}
return false;
}
bool isInterleave(string s1, string s2, string s3) {
if (s1.size() + s2.size() != s3.size()) {
return false;
}
return find(s1, s2, s3);
}
};
虽然算法很优美,但奈何还是倒在了timelimit这一关。
改进了一丢丢的深搜法
所以我们要想一下,为什么一开始的深搜会跑得那么慢,时间都消耗在哪一步了呢?递归最大的弊端在于重复计算,考虑这样一种情况:某时刻s1和s2的前5和前4个字符串构成了s3的前九个,记为(5,4)。接下来,是(6,4),(6,5)…但最终无法完成匹配。于是程序重新回到了(5,4),接下来是(5,5),(6,5),在上述那种算法下,就会重复计算(6,5)之后注定会错误的解。
改进思路:
- 记录所走过的路径。
- 考虑当s1已经全部加入s3时,只需比较s2和s3剩余的部分是否一致。
class Solution {
int m[200][200];
public:
bool dfs(string s1, string s2, string s3, int i1, int i2, int i3) {
if (m[i1][i2]) {
return false;
}
if (i2 == s2.size()) {
return (s1.substr(i1)==s3.substr(i3));
}
if (i1 == s1.size()) {
return (s2.substr(i2)==s3.substr(i3));
}
if (s1[i1] == s3[i3] && dfs(s1, s2, s3, i1+1, i2, i3+1)) {
return true;
}
if (s2[i2] == s3[i3] && dfs(s1, s2, s3, i1, i2+1, i3+1)) {
return true;
}
m[i1][i2] = 1;
return false;
}
bool isInterleave(string s1, string s2, string s3) {
if (s1.size() + s2.size() != s3.size()) {
return false;
}
return dfs(s1, s2, s3, 0, 0, 0);
}
};
嘻嘻嘻,撒花儿~