原題如下:
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);
}