原题如下:
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.
解法一:可以采用递归调用,即依次遍历字符串S3,判断当前字符是来自s1还是来自s2,这里存在的问题是如果当前字符与s1和s2的当前字符都相等的话需要两边都进行尝试,所以其复杂度比较高(为O(mnk)),在leetcode上运行超大字符串时出现超时现象。
bool isInterleave(string s1, string s2, string s3) {
if(s1.length() + s2.length() != s3.length())
return false;
return rec(s1,0,s2,0,s3,0);
}
bool rec(string s1,int p1,string s2,int p2,string s3,int p3){
if(p3 == s3.length())
return true;
if(p1 == s1.length())
return s2.substr(p2) == s3.substr(p3);
if(p2 == s2.length())
return s1.substr(p1) == s3.substr(p3);
if(s1[p1] == s3[p3] && s2[p2] == s3[p3])
return rec(s1,p1+1,s2,p2,s3,p3+1) || rec(s1,p1,s2,p2 + 1,s3,p3+1);
if(s1[p1] == s3[p3])
return rec(s1,p1+1,s2,p2,s3,p3+1);
if(s2[p2] == s3[p3])
return rec(s1,p1,s2,p2 + 1,s3,p3+1);
return false;
}
解法二:采用动态规划思想,这里需要创建(m+1)*(n+1)的二维矩阵,其中m为s1的长度,n为s2的长度,矩阵vv[i[j]表示已s1中前i个字符和s2中前j个字符能否组成s3中前i+j-1个字符。针对矩阵中的每一个单元,都需要判断两次,(画出二维矩阵图后比较容易理解),这种算法的时间复杂度是O(m*n)。
bool isInterleave(string s1, string s2, string s3) {
int len1 = s1.length();
int len2 = s2.length();
int len3 = s3.length();
if(len1 + len2 != len3)
return false;
vector<vector<int>>vv(len1 + 1);
for(int i = 0; i <len1 + 1; i++ ){
vv[i] = vector<int>(len2 + 1);
}
vv[0][0] = 1;
for(int i = 1 ; i < len1 + 1; i++)
{
if(vv[i-1][0] == 1 && s1[i - 1] == s3[i -1])
vv[i][0] = 1;
else
vv[i][0] = 0;
}
for(int j = 1; j < len2 + 1; j++){
if(vv[0][j - 1] == 1 && s2[j - 1] == s3[j - 1])
vv[0][j] = 1;
else
vv[0][j] = 0;
}
for(int i = 1; i < len1+ 1;i ++){
for(int j = 1; j < len2 + 1;j++){
if(s1[i - 1] == s3[i + j - 1] && vv[i - 1][j] ==1 ||s2[j-1] == s3[i + j - 1] && vv[i][j - 1] == 1)
vv[i][j] =1;
else
vv[i][j] = 0;
}
}
return vv[len1][len2];
//return rec(s1,0,s2,0,s3,0);
}