问题描述:
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组成,用s3[i]表示s3的前 i 位,它一定由s1的前m位s1[m]和s2的前n位s2[n]组成,其中m+n=i. 这种情况下我们遍历所有组成情况就好了。
比如 i = 4,只需要判断 (s1[0],s2[4]),(s1[1],s2[3]),(s1[2],s2[2]),(s1[3],s2[1]), (s1[4],s2[0]).
这样看的话DFS就可以搞了,但是为了更高效,我还是找找DP是不是可以搞。
递推公式这样,建立二维数组, 假设p[m][n]表示(s1[m],s2[n])可不可以表达(m+n+长度的s3。这时只需要考虑p[i-1][j] 和p[i][j-1]两个位置:
1. 第一种情况是:p[m-1][n] == true && s1[m] = s3[i],这意味着(s1[m-1],s2[n])可以组成 s3[m+n-1]长度的串,如果s1的第m位 s1[m] == s3的第m+n位,s3[i],那么p[m][n] 就是可匹配的。
2.第二种情况是: p[m][n-1] == true && s2[n] = s3[i],同上分析,只不过s3的第m+n位是s2[n]匹配的而已。
我做了下简化,用好了一维数组,看过背包九讲的大概知道DP可以把空间复杂度从二维降到一维。只是遍历的时候是逆序,并且注意下边界判断即可:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int m = s1.size();
if(m + s2.size() != s3.size()) return false;
bool t[m + 1];
t[0] = 1;
for(int i = 0; i < s3.size(); i++){
bool ct = true;
for(int j = min(m,i + 1); j > 0; j--){
if(t[j] && s2[i - j] == s3[i]) ct = false;
else if(t[j - 1] && s1[j - 1] == s3[i]) { t[j] = true; ct = false;}
else t[j] = false;
}
if(t[0] && s2[i] == s3[i]) ct = false;
if(ct) return false;
}
return true;
}
};