好题呀,太长时间不思考了,想到了分治方法,没坚持下去,也就没想出来,其实不难,就是把s1分为两个串a1,a2;s2分为两个串b1,b2,只要长度相同而且能对应上(就是可以通过交换得来)就可以了,然后递归判断每个子串。下面是递归的方案:
bool isScramble(string s1, string s2) {
int lens1,lens2;
lens1 = s1.length();
lens2 = s2.length();
if(lens1!=lens2)
return false;
if(lens1==0)
return true;
if (lens1==1)
{
return s1[0]==s2[0];
}
if (lens2==2)
{
return (s1[0]==s2[0]&&s1[1]==s2[1])||(s1[0]==s2[1]&&s1[1]==s2[0]);
}
string stra1,stra2,strb1,strb2;
for(int i=1;i<lens1;i++)
{
stra1 = s1.substr(0,i);
stra2 = s1.substr(i,lens1-i);
strb1 = s2.substr(0,i);
strb2 = s2.substr(i,lens2-i);
if (isScramble(stra1,strb1)&&isScramble(stra2,strb2))
{
return true;
}
stra1 = s1.substr(0,lens1-i);
stra2 = s1.substr(lens1-i,i);
if (isScramble(stra1,strb2)&&isScramble(stra2,strb1))
{
return true;
}
}
return false;
}
下面是别人的动态规划方法,看似复杂,其实也不难,所以才是好题呀,没做出来,白瞎了。
class Solution {
private:
bool f[100][100][100];
public:
bool isScramble(string s1, string s2) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if (s1.size() != s2.size())
return false;
for(int i = 0; i < s1.size(); i++)
for(int j = 0; j < s2.size(); j++)
f[1][i][j] = (s1[i] == s2[j]);
for(int len = 2; len <= s1.size(); len++)
{
for(int s1Beg = 0; s1Beg < s1.size(); s1Beg++)
{
int s1End = s1Beg + len - 1;
if (s1End >= s1.size())
break;
for(int s2Beg = 0; s2Beg < s2.size(); s2Beg++)
{
int s2End = s2Beg + len - 1;
if (s2End >= s2.size())
break;
f[len][s1Beg][s2Beg] = false;
for(int s1Mid = s1Beg; s1Mid < s1End; s1Mid++)
{
int leftSize = s1Mid - s1Beg + 1;
int rightSize = len - leftSize;
int s2Mid = s2Beg + leftSize - 1;
bool res1 = f[leftSize][s1Beg][s2Beg] && f[rightSize][s1Mid+1][s2Mid+1];
s2Mid = s2End - leftSize;
bool res2 = f[leftSize][s1Beg][s2Mid+1] && f[rightSize][s1Mid+1][s2Beg];
f[len][s1Beg][s2Beg] = f[len][s1Beg][s2Beg] || res1 || res2;
}
}
}
}
return f[s1.size()][0][0];
}
};
下面的方法是过了两天重新思考后自己写,思路还是一样的,但时间比上面的算法快了一倍。可能是上面算法中每次调用size函数增加了不少时间。别的也没什么差别。
bool isScramble03(string s1, string s2) {
int lens1,lens2;
lens1 = s1.length();
lens2 = s2.length();
if(lens1!=lens2)
return false;
if(lens1==0)
return true;
if (lens1==1)
{
return s1[0]==s2[0];
}
if (lens2==2)
{
return (s1[0]==s2[0]&&s1[1]==s2[1])||(s1[0]==s2[1]&&s1[1]==s2[0]);
}
bool dp[100][100][100];
for (int i=0;i<lens1;i++)
{
for (int j=0;j<lens2;j++)
{
dp[1][i][j] = (s1[i]==s2[j]);
}
}
int i,j,k,t;
for (k=2;k<=lens1;k++)
{
for (i=0;i<lens1;i++)
{
if(i+k>lens1)
break;
for (j=0;j<lens2;j++)
{
if(j+k>lens2)
break;
for (t=1;t<k;t++)
{
if (dp[t][i][j]&dp[k-t][i+t][j+t]|dp[t][i][j+k-t]&dp[k-t][i+t][j])
{
dp[k][i][j] = true;
break;
}
}
if(t==k)
dp[k][i][j] = false;
}
}
}
return dp[lens1][0][0];
}
路是走出来,不是想出来的。这种方法也是慢慢想出来的,开始没思路,举了几个简单的例子就有思路了,一点点就总结出规律来了,凡事都如此吧,放弃了,就是永远失败了。