Interleaving String
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
解法1:動態規劃
構造一個二維數組,dp[i][j]表示字符串到位置i和字符串s2到位置j能組成s3
dp[0][0]=1;
當i=0時,dp[i][j] = dp[i][j-1] && s2[j-1] == s3[j-1];
當j=0時,dp[i][j] = dp[i-1][j] && s1[i-1] == s3[i-1];
否則:dp[i][j] = (dp[i-1][j] && s1[i-1]==s3[i+j-1]) || (dp[i][j-1] && s2[j-1]==s3[i+j-1]);
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s1.size()+s2.size() != s3.size()) return false;
int n1=s1.size(),n2=s2.size();
vector<vector<bool>> dp(n1+1,vector<bool>(n2+1));
for(int i=0;i<=n1;i++){
for(int j=0;j<=n2;j++){
if(i==0 && j==0)
dp[i][j] = 1;
else if(i==0)
dp[i][j] = dp[i][j-1] && s2[j-1] == s3[j-1];
else if(j==0)
dp[i][j] = dp[i-1][j] && s1[i-1] == s3[i-1];
else
dp[i][j] = (dp[i-1][j] && s1[i-1]==s3[i+j-1]) || (dp[i][j-1] && s2[j-1]==s3[i+j-1]);
}
}
return dp[n1][n2];
}
};
解法2:DFS
使用一個hashmap來記錄匹配失敗的情況,存的值爲key=i*s3.size()+j來表示一對(i,j);
i表示s1當前的位置,j表示s2當前的位置。
當i=s1.size;判斷s2剩餘的部分和s3剩餘部分是否相等;
當j=s2.size;判斷s1剩餘的部分和s3剩餘部分是否相等;
否則,如果s1[i]==s3[k] 調用遞歸函數helper(s1,i+1,s2,j,s3,k+1,s))
或者s2[j]==s3[k],helper(s1,i,s2,j+1,s3,k+1, s)
把匹配失敗的key加入到hashmap中。
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s1.size()+s2.size() != s3.size()) return false;
unordered_set<int> s;
return helper(s1, 0, s2, 0, s3, 0, s);
}
bool helper(string s1, int i, string s2, int j, string s3,int k, unordered_set<int>& s){
int key = i * s3.size() + j;
if (s.count(key)) return false;
if(i==s1.size()) return s2.substr(j) == s3.substr(k);
if(j==s2.size()) return s1.substr(i) == s3.substr(k);
if((s1[i]==s3[k] && helper(s1,i+1,s2,j,s3,k+1,s)) || (s2[j]==s3[k] && helper(s1,i,s2,j+1,s3,k+1, s)))
return true;
s.insert(key);
return false;
}
};
解法3:BFS
用一個隊列來輔助BFS,循環 queue 中元素個數的次數,在 for 循環中,對隊首元素進行解碼,得到i和j值,
如果i小於 n1,說明 s1 還有剩餘字符,如果 s1 當前字符等於 s3 當前字符,那麼把 s1 的下一個位置 i+1 跟j一起加碼算出 key 值,如果該 key 值不在於集合中,則加入集合,同時加入隊列 queue 中;
同理,如果j小於 n2,說明 s2 還有剩餘字符,如果 s2 當前字符等於 s3 當前字符,那麼把 s2 的下一個位置 j+1 跟i一起加碼算出 key 值,如果該 key 值不在於集合中,則加入集合,同時加入隊列 queue 中。
for 循環結束後,k自增1。最後如果匹配成功的話,那麼 queue 中應該只有一個 (n1, n2) 的 key 值,且k此時等於 n3,所以當 queue 爲空或者k不等於 n3 的時候都要返回 false,
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s1.size()+s2.size() != s3.size()) return false;
int n1=s1.size(),n2=s2.size(),n3=s3.size();
unordered_set<int> s;
queue<int> q;
q.push(0);
int i=0,j=0,k=0;
while(!q.empty() && k<n3){
int len = q.size();
for(int t=0;t<len;t++){
i = q.front() / n3;
j = q.front() % n3;
q.pop();
if (i < n1 && s1[i] == s3[k]) {
int key = (i + 1) * n3 + j;
if (!s.count(key)) {
s.insert(key);
q.push(key);
}
}
if (j < n2 && s2[j] == s3[k]) {
int key = i * n3 + j + 1;
if (!s.count(key)) {
s.insert(key);
q.push(key);
}
}
}
k++;
}
return !q.empty() && k == n3;
}
};