[Lc]87扰乱字符串
Contents
题目
题解
1. 递归法
就是通过递归左右子串,首先判断长度是否相等,不相等直接false;然后判断是否完全一样,一样直接true;然后判断排序后是否相等,不相等也false,接下来分两种情况递归,
即1左=2左且1右=2右,
或1左=2右且1右=2左,
=表示互为scramble,细节见注释
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size()) return false;//长度不一样,直接返回false
if(s1 == s2) return true;//完全一样,返回true
string sort_s1 = s1, sort_s2 = s2;
sort(sort_s1.begin(), sort_s1.end());
sort(sort_s2.begin(), sort_s2.end());
if(sort_s1 != sort_s2) return false;//比较两个排序后的数组,不一样直接返回false
for(int i=1; i<s1.size(); ++i){
//在每个点对两个字符串进行划分,然后进行递归对比,有两种情况,具体看题解和下面
string s11 = s1.substr(0,i);
string s12 = s1.substr(i);
string s21 = s2.substr(0,i);
string s22 = s2.substr(i);
if(isScramble(s11,s21) && isScramble(s12,s22)) return true;//情况一
//注意这两行,情况二的s2左右子串长度于情况一相反
s21 = s2.substr(0, s1.size()-i);
s22 = s2.substr(s1.size()-i);
if(isScramble(s11,s22) && isScramble(s12,s21)) return true;//情况二
}
return false;//若全部遍历完还没有返回true说明不是scramble,返回false
}
};
2. 动态规划
炒鸡难,看了(https://www.cnblogs.com/grandyang/p/4318500.html)和(https://leetcode-cn.com/problems/scramble-string/solution/miao-dong-de-qu-jian-xing-dpsi-lu-by-sha-yu-la-jia/)才懂得,那个状态转移矩阵比较麻烦,而且是三维的dp,详细看上述博客和注释吧。
- 时间复杂度$O(n^{4})$,三维dp矩阵和一个状态转移时的遍历
- 空间复杂度$O(n^{3})$,三维dp
//动态规划,这个有点难了,其实原理和递归类似,也是判断划分后左右的子串是否是scramble
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size()) return false;//长度不一样,直接返回false
if(s1 == s2) return true;//完全一样,返回true
int n = s1.size();
//创建三维状态转移数数组,len是n+1.其中0是空的,长度为0的不考虑,1~n有值
//其实这个数组应该是一个四分之一的金字塔形,越往上越小,下面内层的两个循环用n-len就说明这一点
//可以在脑中想象这个图形
//int dp[n][n][n+1];
vector<vector<vector<bool>>> dp(n,vector<vector<bool>>(n,vector<bool>(n+1,false)));
for(int len=1; len<=n; ++len){
for(int i=0; i<=n-len; ++i){
for(int j=0; j<=n-len; ++j){
if(len == 1) dp[i][j][len] = (s1[i] == s2[j]);
else{
for(int k=1; k<len; ++k){//遍历每一种劈法
//状态转移方程,只要有一种劈法1左=2左且1右=2右,或1左=2右且1右=2左就可以,=表示互为scramble
//注意第二种情况的括号内的数字,两个不完全一样,一个+k,一个+len-k
if((dp[i][j][k] && dp[i+k][j+k][len-k])||(dp[i][j+k][len-k] && dp[i+len-k][j][k])){
dp[i][j][len] = true;
break;//有一种情况成立就可以break
}
}
}
}
}
}
return dp[0][0][n];
}
};
Author ChrisHRZ
LastMod 2020-05-06