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;
}
};