coder/ \co der/ \ / \c o d er/ \e r
ocder/ \oc der/ \ / \o c d er/ \e r
ocred / \ oc red / \ / \ o c re d / \ r e我们称"ocred"是"coder"的一个乱序字符串。
coder/ \co der/ \ / \c o d er/ \e r
ocder/ \oc der/ \ / \o c d er/ \e r
ocred / \ oc red / \ / \ o c re d / \ r e我们称"ocred"是"coder"的一个乱序字符串。
"ab","ab"
true
"ba","ab"
true
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1 == s2)
return true;
int c[26] = {0};
for(int i=0;i<s1.length();i++)
{
c[s1[i]-'a']++;
c[s2[i]-'a']--;
}
for(int i=0;i<26;i++)
if(c[i] != 0)
return false;
for(int i=1;i<s1.length();i++)
{
if(isScramble(s1.substr(0,i), s2.substr(0,i)) && isScramble(s1.substr(i), s2.substr(i)))
return true;
if(isScramble(s1.substr(0,i), s2.substr(s2.length()-i)) && isScramble(s1.substr(i), s2.substr(0,s2.length()-i)))
return true;
}
return false;
}
}; /*
* 参考自leetcode网友:@baifriend
*/
public boolean isScramble(String s1, String s2) {
if (s1.equals(s2))
return true;
int[] letters = new int[26];
for (int i = 0; i < s1.length(); i++) {
letters[s1.charAt(i) - 'a']++;
letters[s2.charAt(i) - 'a']--;
}
for (int i = 0; i < 26; i++)
if (letters[i] != 0)
return false;
for (int i = 1; i < s1.length(); i++) {
if (isScramble(s1.substring(0, i), s2.substring(0, i))
&& isScramble(s1.substring(i), s2.substring(i)))
return true;
if (isScramble(s1.substring(0, i), s2.substring(s2.length() - i))
&& isScramble(s1.substring(i), s2.substring(0, s2.length() - i)))
return true;
}
return false;
}
/*
* 思路:从简单情况开始,
* 1.两个字符串都只有一个字符时只需比较是否相等
* 2.字符个数大于一时,先判断长度是否相等,在判断是否由相同的字符组成,若否则直接返回false
* 3.分隔字符串,有两种情况,一种是不交换,一种是左右交换
*/
public class Solution {
public boolean isScramble(String s1, String s2) {
int len1 = s1.length();
int len2 = s2.length();
if (len1 != len2)
return false;
if (len1 == 1)
return s1.equals(s2);
//剪枝:若排序后不不相等则必定不满足条件
char[] chars1 = new char[len1];
s1.getChars(0, len1, chars1, 0);
Arrays.sort(chars1);
char[] chars2 = new char[len1];
s2.getChars(0, len2, chars2, 0);
Arrays.sort(chars2);
if (!(new String(chars1).equals(new String(chars2))))
return false;
for (int i = 1; i < len1; i++) {
String s1left = s1.substring(0, i);
String s1right = s1.substring(i, len1);
String s2left = s2.substring(0, i);
String s2right = s2.substring(i, len1);
//在当前分割处没有交换
if (isScramble(s1left, s2left) && isScramble(s1right, s2right))
return true;
//当前分割处左右交换
s2right = s2.substring(len1 - i, len1);
s2left = s2.substring(0, len1 - i);
if (isScramble(s1left, s2right) && isScramble(s1right, s2left))
return true;
}
return false;
}
}
import java.util.*;
public class Solution {
/*
题意:求s2是不是s1的爬行字符串,其实就是s1任意交换字母,看能不能交换成s2
1、当s1,s2长度为1时,直接判断s1==s2即可获得答案
2、当s1为ab,那么s2只能ab或者ba
3、
例如:
3.1、gr|eat 和 rg|eat从第2个位置进行分割,不进行交换
a1=gr b1=eat a2=rg b2=eat
此时需要判断
(gr, rg) && (eat, eat)
3.2、对于 re|at 和 ta|er从第2个位置进行分割
a1=re b1=at a2=ta b2=er,这种显然这种是不符合的
那么s2的两部分交换,那么s'=er|ta
a1=re b1=at a2`=er b2`=ta,这种显然是符合条件的
对于任意长度的字符串,我们可以把字符串s1分为a1,b1两部,s2分为a2,b2两部分
满足 (a1~a2) && (b1~b2) || (a1~b2) && (a2~b1)
4、剪枝,判断两个字符串是否有相同的字符集,没有则直接剪去这个分支
*/
public boolean isScramble(String s1, String s2) {
int len1 = s1.length();
int len2 = s2.length();
if (len1 != len2) {
return false;
}
if(len1 == 1) {
return s1.equals(s2);
}
char[] chs1 = s1.toCharArray();
char[] chs2 = s2.toCharArray();
Arrays.sort(chs1);
Arrays.sort(chs2);
String sortS1 = new String(chs1);
String sortS2 = new String(chs2);
if (!sortS1.equals(sortS2)) {
return false;
}
for(int i = 1; i < len1; i++) {
String s1Left = s1.substring(0, i);
String s1Right = s1.substring(i, len1);
String s2Left = s2.substring(0, i);
String s2Right = s2.substring(i, len1);
// 没有交换
if(isScramble(s1Left, s2Left) && isScramble(s1Right, s2Right)) {
return true;
}
// 交换比较
s2Right = s2.substring(len1 - i, len1);
s2Left = s2.substring(0, len1 - i);
if(isScramble(s1Left, s2Right) && isScramble(s1Right, s2Left)) {
return true;
}
}
return false;
}
}
/**
* 定义了一种爬行字符串,
* 假如把一个字符串当做一个二叉树的根,
* 然后它的非空子字符串是它的子节点,
* 然后交换某个子字符串的两个子节点,
* 重新爬行回去形成一个新的字符串,
* 这个新字符串和原来的字符串互为爬行字符串。
*
* 思路:递归
* 简单的说,就是s1和s2是scramble的话,
* 那么必然存在一个在s1上的长度l1,
* 将s1分成s11和s12两段,同样有s21和s22.
* 那么要么s11和s21是scramble的并且s12和s22是scramble的;
* 要么s11和s22是scramble的并且s12和s21是scramble的。
* 就拿题目中的例子 rgeat 和 great 来说,
* rgeat 可分成 rg 和 eat 两段,
* great 可分成 gr 和 eat 两段,
* rg 和 gr 是scrambled的, eat 和 eat 当然是scrambled。
*
* 摘自https://www.cnblogs.com/grandyang/p/4318500.html
**/
import java.util.Arrays;
public class Solution {
public boolean isScramble(String s1, String s2) {
if (s1.length() != s2.length()) {
return false;
}
if (s1.equals(s2)) {
return true;
}
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
Arrays.sort(c1);
Arrays.sort(c2);
if (!Arrays.equals(c1, c2)) {
return false;
}
for (int i = 1; i < s1.length(); i++) {
if (isScramble(s1.substring(0, i), s2.substring(0, i))
&& isScramble(s1.substring(i), s2.substring(i))) {
return true;
}
if (isScramble(s1.substring(0, i), s2.substring(s2.length() - i))
&& isScramble(s1.substring(i), s2.substring(0, s2.length() - i))) {
return true;
}
}
return false;
}
}
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1==s2) return true;
int A[26]={0};
for(int i=0;i<s1.length();++i){
A[s1[i]-'a']++;
A[s2[i]-'a']--;
}
for(int i=0;i<26;++i){
if(A[i]!=0) return false;
}
for(int i=1;i<s1.length();++i){
if(isScramble(s1.substr(0,i),s2.substr(0,i)) && isScramble(s1.substr(i),s2.substr(i))
|| isScramble(s1.substr(0,i),s2.substr(s2.length()-i)) && isScramble(s1.substr(i),s2.substr(0,s2.length()-i))) return true;
}
return false;
}
}; }
#include <iostream>
#include <string>
using namespace std;
class Solution {
public:
bool isScramble(string s1, string s2);
};
bool Solution::isScramble(string s1, string s2) {
if (s1.size() != s2.size()) {
return false;
}
const int len = s1.length();
//DP[k][i][j] 表示s2的从j开始长度为k的子串是否为s1的从i开始长度为k的子串的scramble string
bool DP[len+1][len][len] = {false};
//初始化DP[1][i][j],长度为1的子串,只要相等就是scramble string
for (int i=0; i<len; ++i) {
for (int j=0; j<len; ++j) {
DP[1][i][j] = (s1[i]==s2[j]) ? true : false;
}
}
for (int k=2; k<=len; ++k) {
for (int i=0; i<=len-k; ++i) {
for (int j=0; j<=len-k; ++j) {
//div表示长度为k的子串中,将子串一分为二的分割点
for (int div=1; div<k && !DP[k][i][j]; ++div) {
// DP[k][i][j] = true的条件是子串分割后的两段对应相等,或者交叉对应相等
if ((DP[div][i][j]&&DP[k-div][i+div][j+div])
|| (DP[div][i][j+k-div]&&DP[k-div][i+div][j])) {
DP[k][i][j] = true;
}
}
}
}
}
return DP[len][0][0];
}
int main(int argc, char const *argv[]) {
string s1 = "tt";
string s2 = "tb";
Solution so;
bool res = so.isScramble(s1, s2);
return res;
}
//参考高票回答,思路简单,代码精简,忍不住描摹了一下
//使用数组计数实现s1,s2对应子树的字符串包含的字符是否相同,不同直接返回false
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1 == s2)
return true;
int c[26] = {0};
for(int i=0;i<s1.size();i++)
{
c[s1[i]-'a']++;
c[s2[i]-'a']--;
}
for(int j=0;j<26;j++)
{
if(c[j] != 0)
return false;
}
for(int k=1;k<s1.size();k++)
{
if(isScramble(s1.substr(0,k),s2.substr(0,k)) && isScramble(s1.substr(k),s2.substr(k)))
return true;
if(isScramble(s1.substr(0,k),s2.substr(s2.size()-k)) && isScramble(s1.substr(k),s2.substr(0,s2.size()-k)))
return true;
}
return false;
}
};
这样会很耗内存吗? 通不过,求解答 bool isScramble(string s1, string s2) {
int n=s1.size();
if(n==1 && s1==s2)
return true;
if(n==1 && s1!=s2)
return false;
vector<string> res;
res.push_back(s1.substr(0,1));
for( int i = 0 ; i < n-1 ; i ++ )
{
int t = res.size();
for(int j=0; j < t ; j++)
{
string tmp=res[j];
//原有的不能保存在里面
res[j] = res[j]+s1[i+1];
res.push_back(s1[i+1]+tmp);
}
}
for(int j = 0; j < res.size(); j++)
{
cout<< res[j]<<endl;
if(s2==res[j])
return true;
}
return false;
}
import java.util.*;
public class Solution {
public boolean isScramble(String s1, String s2) {
if(s1.length() != s2.length()) return false;
if(s1.length() == 1 || s2.length() == 1) return s1.equals(s2);
char[] arr1 = s1.toCharArray();
char[] arr2 = s2.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
for (int i = 0; i < arr1.length; i ++) {
if(arr1[i] != arr2[i]) return false;
}
for (int i = 1; i < s1.length(); i ++) {
String s1left = s1.substring(0, i);
String s1rigt = s1.substring(i);
String s2left = s2.substring(0, i);
String s2right = s2.substring(i);
if(isScramble(s1left, s2left) && isScramble(s1rigt, s2right)) return true;
s2left = s2.substring(0, s2.length() - i);
s2right = s2.substring(s2.length() - i);
if(isScramble(s1left, s2right) && isScramble(s1rigt, s2left)) return true;
}
return false;
}
}
牛客的标签里面有“动态规划”,搞得我一脸懵逼😳
本题应该用递归/贪心实现,条件如下:
代码如下:
//
// Created by jt on 2020/8/30.
//
#include <string>
#include <unordered_map>
using namespace std;
class Solution {
public:
/**
*
* @param s1 string字符串
* @param s2 string字符串
* @return bool布尔型
*/
bool isScramble(string s1, string s2) {
// write code here
return dfs(s1, s2);
}
bool dfs(string s1, string s2) {
if (s1.size() != s2.size()) return false;
if (s1 == s2) return true;
unordered_map<char, int> um;
for (int i = 0; i < s1.size(); ++i) {
++um[s1[i]]; --um[s2[i]];
}
for (auto it = um.begin(); it != um.end(); ++it) {
if (it->second != 0) return false;
}
for (int i = 1; i < s1.size(); ++i) {
if (dfs(s1.substr(0, i), s2.substr(0, i)) &&
dfs(s1.substr(i), s2.substr(i))) return true;
if (dfs(s1.substr(0, i), s2.substr(s1.size()-i)) &&
dfs(s1.substr(i), s2.substr(0, s1.size()-i))) return true;
}
return false;
}
};
class Solution:
def isScramble(self , s1 , s2 ):
# write code here
if s1 == s2:
return True
if len(s1) != len(s2):
return False
chars = [0]*26 # 判断是否字符串的字母都一样
l = len(s2)
for i in range(l):
chars[ord(s1[i])-ord('a')] += 1
chars[ord(s2[i])-ord('a')] -= 1
for i in chars:
if i != 0:
return False
for i in range(1,l): # 从1开始
if self.isScramble(s1[:i], s2[:i]) & self.isScramble(s1[i:],s2[i:]):
return True
if self.isScramble(s1[:i], s2[-i:]) & self.isScramble(s1[i:],s2[:-i]): #对调
return True
return False /*
* 目的:乱序字符串
* 方法:参考大佬的
* 1.两个字符串都只有一个字符时只需比较是否相等
* 2.字符个数大于一时,先判断长度是否相等,在判断是否由相同的字符组成,若否则直接返回false
* 3.分隔字符串,有两种情况,一种是不交换,一种是左右交换
*/
bool isValid(string s1, string s2){
sort(s1.begin(),s1.end());
sort(s2.begin(),s2.end());
return s1==s2;
}
bool isScramble(string s1, string s2) {
if (s1.size()!=s2.size())
return false;
if (s1.empty() || s1==s2)
return true;
if (!isValid(s1,s2)){
return false;
}
for (int i = 1;i<s1.size();++i){
string left = s1.substr(0,i);
string right = s1.substr(i,s1.size()-i);
if (isScramble(left,s2.substr(0,i))&&
isScramble(right,s2.substr(i,s2.size()-i)))
return true;
if (isScramble(right,s2.substr(0,right.size()))&
&isScramble(left,s2.substr(right.size(),i)))
return true;
}
return false;
}
//扰乱字符串可以分成两部分进行递归,第一个部分A,第二部分B,A和B分别时对应子串的扰乱字符串
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1.size()!=s2.size())
return false;
if(s1.size()==0||s1==s2)
return true;
string ss1=s1,ss2=s2;
sort(ss1.begin(),ss1.end());
sort(ss2.begin(),ss2.end());
if(ss1!=ss2)
return false;
//将s2字符串切分为前i个字符和后s2.size()-i个字符
for(int i=1;i<s2.size();i++){
//s1前i个字符和s2前i个字符配对
//s1前i个字符和s2后i个字符配对
if((isScramble(s1.substr(0,i), s2.substr(0,i))&&
isScramble(s1.substr(i), s2.substr(i)))||
(isScramble(s1.substr(0,i), s2.substr(s2.size()-i))&&
isScramble(s1.substr(i), s2.substr(0,s2.size()-i))))
return true;
}
return false;
}
};