参考链接
http://www.blogjava.net/sandy/archive/2013/05/10/398754.html
题目描述
Interleaving String
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的某个字符。如果都不相等,则返回false
我们使用3个变量i,j,k分别记录当前s1,s2,s3的字符位置。
如果s3[k] = s1[i], i向后移动一位。如果s3[k]=s2[j],j向后移动一位。
这个题目主要难在如果s1和s2的字符出现重复的时候,就有两种情况,i,j都可以向后一位。
下面的算法在这种情况使用了递归,很简单的做法。但是效率非常差,是指数复杂度的。
一个简单的想法,是遍历s3的每个字符,这个字符必须等于s1和s2的某个字符。如果都不相等,则返回false
我们使用3个变量i,j,k分别记录当前s1,s2,s3的字符位置。
如果s3[k] = s1[i], i向后移动一位。如果s3[k]=s2[j],j向后移动一位。
这个题目主要难在如果s1和s2的字符出现重复的时候,就有两种情况,i,j都可以向后一位。
下面的算法在这种情况使用了递归,很简单的做法。但是效率非常差,是指数复杂度的。
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s3.size() != (s1.size() + s2.size())) return false;
return isInterleaveCore(s1,0,s2,0,s3,0);
}
bool isInterleaveCore(const string &s1,int index1,const string &s2,int index2, const string &s3,int index3)
{
if(index3 == s3.size()) return true;
//printf("%d-%d-%d\n");
if(s1[index1] == s3[index3] && isInterleaveCore(s1,index1+1,s2,index2,s3,index3+1)) return true;
if(s2[index2] == s3[index3] && isInterleaveCore(s1,index1,s2,index2+1,s3,index3+1)) return true;
return false;
}
};
解法二:(动态规划)
为了减少重复计算,就要使用动态规划来记录中间结果。
这里我使用了一个二维数组result[i][j]来表示s1的前i个字符和s2的前j个字符是否能和s3的前i+j个字符匹配。
状态转移方程如下:
result[i,j] = (result[i-1,j] && s1[i] = s3[i+j]) || (result[i,j-1] && s2[j] = s3[i+j]);
其中0≤i≤len(s1) ,0≤j≤len(s2)
为了减少重复计算,就要使用动态规划来记录中间结果。
这里我使用了一个二维数组result[i][j]来表示s1的前i个字符和s2的前j个字符是否能和s3的前i+j个字符匹配。
状态转移方程如下:
result[i,j] = (result[i-1,j] && s1[i] = s3[i+j]) || (result[i,j-1] && s2[j] = s3[i+j]);
其中0≤i≤len(s1) ,0≤j≤len(s2)
这样算法复杂度就会下降到O(l1*l2)
class Solution {
private:
bool f[1000][1000];
public:
bool isInterleave(string s1, string s2, string s3) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if (s1.size() + s2.size() != s3.size())
return false;
f[0][0] = true;
for(int i = 1; i <= s1.size(); i++)
f[i][0] = f[i-1][0] && (s3[i-1] == s1[i-1]);
for(int j = 1; j <= s2.size(); j++)
f[0][j] = f[0][j-1] && (s3[j-1] == s2[j-1]);
for(int i = 1; i <= s1.size(); i++)
for(int j = 1; j <= s2.size(); j++)
f[i][j] = (f[i][j-1] && s2[j-1] == s3[i+j-1]) || (f[i-1][j] && s1[i-1] == s3[i+j-1]);
return f[s1.size()][s2.size()];
}
};
总结
代码示例
推荐学习C++的资料
C++标准函数库
在线C++API查询