给定2个字符串,判断是否能够通过重排列这2个字符串而产生另外一个字符串
RT,给定字符串s1,s2判断能否通过重排列 s1 s2从而产生s3.注意s1 s2中字符的相对顺序不能变。
如:
s1 = abc
s2 = def
s3 = abcdef return true
s3 = adefbc return true
s3 = aefdbc return false
思路:
1.递归,很简单的思路,代码如下:
bool Can(string s1, string s2, string s3) {
if (s3.size() != s1.size() + s2.size())
return false;
if (s1.size() == 0 && s2 == s3 )
return true;
if (s2.size() == 0 && s1 == s3)
return true;
if (s1[0] == s3[0]) {
if(isInterleave(s1.substr(1, s1.size() - 1),s2, s3.substr(1, s3.size() - 1)))
return true;
}
if (s2[0] == s3[0]) {
if(isInterleave(s1,s2.substr(1, s2.size() - 1), s3.substr(1, s3.size() - 1)))
return true;
}
return false;
}
递归的思路类似穷举,分析一下复杂度?在没有大量重复字符的时候,递归的复杂度其实还可以,但如果有大量重复字符,这个时间复杂度就难以接受了,有木有更简单的?
2.动态规划,我的理解,递归是一种不保存历史记录的动态规划,如果我们将现场保存,那么递归很容易转化为动态规划。
bool can(string s1, string s2, string s3) {
if (s3.size() != s1.size() + s2.size())
return false;
if (s1.size() == 0) {
if (s2 == s3)
return true;
else
return false;
}
if (s2.size() == 0 ) {
if (s1 == s3)
return true;
else
return false;
}
vector<vector<bool> > dp;
dp.resize(s1.size() + 1);
for (int i = 0; i <= s1.size(); ++i) {
dp[i].resize(s2.size() + 1, false);
for (int j = 0; j <= s2.size(); ++j) {
if (i == 0 && j == 0)
dp[i][j] = true;
else if (i == 0) {
if (s3[i + j - 1] == s2[j - 1] && dp[i][j - 1])
dp[i][j] = true;
} else if (j == 0) {
if (s3[i + j - 1] == s1[i - 1] && dp[i - 1][j])
dp[i][j] = true;
}
else {
if (s3[i + j - 1] == s2[j - 1] && dp[i][j - 1])
dp[i][j] = true;
if (s3[i + j - 1] == s1[i - 1] && dp[i - 1][j])
dp[i][j] = true;
}
}
}
return dp[s1.size()][s2.size()];
}
代码其实写得很罗嗦,基本思想是用一张表记录历史状态,没加入一个新的元素,就可以获取历史计算结果进行参考。空间复杂度为O(N^2)
其实可以进一步缩小空间复杂度的。

浙公网安备 33010602011771号