题目:
给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。
输入输出:
输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" 输出: true
分析:
首先可以分析一下这道题的解空间,比较容易想到的是对于s3中的每个字符我们需要考虑的是用s1或者s2中的字符去代替,这样的话它的解空间应该是o(2^n)的,我们就能想到暴力的解法,再加上一些判断。下面是暴力解法的代码:
class Solution {
public:
bool fb(string s1, string s2, string s3, int a, int b, int c){
if(c == s3.size()){
return true;
}
if(a < s1.size() && b < s2.size() && s1[a] == s3[c] && s2[b] == s3[c]){
return fb(s1, s2, s3, a + 1, b, c + 1) || fb(s1, s2, s3, a, b + 1, c + 1);
}
if(a < s1.size() && s1[a] == s3[c]){
return fb(s1, s2, s3, a + 1, b, c + 1);
}
if(b < s2.size() && s2[b] == s3[c]){
return fb(s1, s2, s3, a, b + 1, c + 1);
}
return false;
}
bool isInterleave(string s1, string s2, string s3) {
if(s1.size() + s2.size() != s3.size()){
return false;
}
return fb(s1, s2, s3, 0, 0, 0);
}
};
思路比较简单,对s1,s2,s3都设一个下标为a, b, c。就是对于s3中的每一个字符,如果s1和s2都和该字符一样则返回s1指针后移
和s2后移结果的或,如果其中一个相同,则返回该下标后移的结果,如果都不相同,则直接返回false。这样的话,它的时间复杂度是o(2^n)的,有点高,运行上面的代码内存会超,所以需要寻找其他的方法。
对于这种指数时间复杂的问题,通常都用动态规划的方法来降低时间复杂度,这个题也是一样的。用一个二维数组dp[i][j]来表示s1下标为i - 1, s2下标为j - 1 的时候能不能匹配当前的s3。那么状态转移方程为:
dp[i][j] = (s1[i - 1] == s3[ i + j - 1] && dp[i - 1][j]) || (s2[j - 1] == s3[i + j - 1] && dp[i][j - 1])
对于位置i,j,可能是通过i匹配得到的,也可能是通过j匹配得到的,所以就有上面的式子,动态规划其实就是通过一个数组来记录之前的状态从而减少搜索的时间。下面是代码:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int len1 = s1.size();
int len2 = s2.size();
if(len1 == 0){
if(s2 == s3) return true;
else return false;
}
if(len2 == 0){
if(s1 == s3) return true;
else return false;
}
vector<vector<bool>> dp(len1 + 1, vector<bool> (len2 + 1, false));
dp[0][0] = true;
if(len1 + len2 != s3.size()){
return false;
}
for(int i = 0; i < len1; ++i)
dp[i + 1][0] = (s1[i] == s3[i] && dp[i][0]);
for(int j = 0; j < len2; ++j)
dp[0][j + 1] = (s2[j] == s3[j] && dp[0][j]);
for(int i = 1; i < len1 + 1; i++){
for(int j = 1; j < len2 + 1; j++){
dp[i][j] = (s1[i - 1] == s3[i + j - 1] && dp[i - 1][j]) || (s2[j - 1] ==
s3[i + j - 1] && dp[i][j - 1]);
}
}
return dp[len1][len2];
}
};
动态规划的时间复杂度是o(n^2)的,思路也是比较清晰,这里的思路优点跟最长公共序列相似。