87. 扰乱字符串

给定一个字符串 s1,我们可以把它递归地分割成两个非空子字符串,从而将其表示为二叉树。

下图是字符串 s1 = “great” 的一种可能的表示形式。

    great
/ \
gr eat
/ \ / \
g r e at
/ \
a t

在扰乱这个字符串的过程中,我们可以挑选任何一个非叶节点,然后交换它的两个子节点。

例如,如果我们挑选非叶节点 “gr” ,交换它的两个子节点,将会产生扰乱字符串 “rgeat” 。

    rgeat
/ \
rg eat
/ \ / \
r g e at
/ \
a t

我们将 "rgeat” 称作 “great” 的一个扰乱字符串。

同样地,如果我们继续交换节点 “eat” 和 “at” 的子节点,将会产生另一个新的扰乱字符串 “rgtae” 。

    rgtae
/ \
rg tae
/ \ / \
r g ta e
/ \
t a

我们将 "rgtae” 称作 “great” 的一个扰乱字符串。

给出两个长度相等的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。

示例 1:

输入: s1 = “great”, s2 = “rgeat”

输出: true

示例 2:

输入: s1 = “abcde”, s2 = “caebd”

输出: false

PS:两种方法dfs执行效率高一点(其实dp的效率应该更高,但小编能力有限了)

class Solution {
public boolean isScramble(String s1, String s2) {
if (s1.length()==0 && s2.length()==0) return true;
if (s1.length()!=s2.length()) return false;
return dfs(s1.toCharArray(), s2.toCharArray(), 0, 0, s1.length());
}
private boolean dfs(char[] s1, char[] s2, int start1, int start2, int len){
if (len==1) {
return s1[start1]==s2[start2];
}
if (!equals(s1, s2, start1, start2, len)) {
return false;
}
for (int i=1; i<len; i++){ //两个字符串是否相等 我的搜索位置往后走i,我的结束就要往前走i防止超限
if (dfs(s1, s2, start1, start2, i) && dfs(s1, s2, start1+i, start2+i, len-i)) return true;
// |i到len-1|这块进行翻转
if (dfs(s1, s2, start1, start2+len-i, i) && dfs(s1, s2, start1+i, start2, len-i)) return true;
}
return false;
}
public boolean equals(char[] s1, char[] s2, int start1, int start2, int len){
int[] charArr = new int[26];
for (int i=0; i<len; i++) {
charArr[s1[start1+i] - 'a']++;
charArr[s2[start2+i] - 'a']--;
}
for (int item : charArr) {
if (item != 0) return false;
}
return true;
}
}
class Solution {
public boolean isScramble(String s1, String s2) {
if(s1==null&&s2!=null||s2==null&&s1!=null||s1.length()!=s2.length()) return false;
boolean[][][] dp=new boolean[s1.length()][s2.length()][s1.length()+1];
//初始化len=1
for (int i = 0; i < s1.length(); i++) {//第一个字符串的起点
for (int j = 0; j < s2.length(); j++) {//第二个字符串的起点
if(s1.charAt(i)==s2.charAt(j)) dp[i][j][1]=true;
}
}
for (int len = 2; len <=s1.length(); len++) {//区间长度
for (int i = 0; i < s1.length(); i++) {//第一个字符串的起点,终点i+len-1
for (int j = 0; j < s2.length(); j++) {//第二个字符串的起点,终点j+len-1
for (int k = 1; k <len; k++) {//左边区间的长度,因为要划分成两个区间,所以左边那个区间的长度是1...len-1(至少为一,至多也得给第二个区间留一个)
if(i+k<s1.length()&&j+k<s1.length()&&j+len-k<s1.length()&&((dp[i][j][k]&&dp[i+k][j+k][len-k])||(dp[i][j+len-k][k]&&dp[i+k][j][len-k]))){
dp[i][j][len]=true;
break;
}
}
}
}
}
return dp[0][0][s1.length()];
}
}

PS:

//dp[i][j][k][l] 表示s1的i-j和s2的k-l是否互为扰乱字符串,因为j-i=l-k,所以优化成 //dp[i][j][k] 表示s1的i...i+k和s2的j...j+k是否互为扰乱字符串

这里有大佬的各种实现方式

Java实现 LeetCode 87 扰乱字符串的更多相关文章

  1. Leetcode 87.扰乱字符串

    扰乱字符串 给定一个字符串 s1,我们可以把它递归地分割成两个非空子字符串,从而将其表示为二叉树. 下图是字符串 s1 = "great" 的一种可能的表示形式. 在扰乱这个字符串 ...

  2. Java实现 LeetCode 557 反转字符串中的单词 III(StringBuilder的翻转和分割)

    557. 反转字符串中的单词 III 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例 1: 输入: "Let's take LeetCode c ...

  3. Java实现 LeetCode 345 反转字符串中的元音字母

    345. 反转字符串中的元音字母 编写一个函数,以字符串作为输入,反转该字符串中的元音字母. 示例 1: 输入: "hello" 输出: "holle" 示例 ...

  4. Java实现 LeetCode 806 写字符串需要的行数 (暴力模拟)

    806. 写字符串需要的行数 我们要把给定的字符串 S 从左到右写到每一行上,每一行的最大宽度为100个单位,如果我们在写某个字母的时候会使这行超过了100 个单位,那么我们应该把这个字母写到下一行. ...

  5. Java实现 LeetCode 796 旋转字符串 (水题)

    796. 旋转字符串 给定两个字符串, A 和 B. A 的旋转操作就是将 A 最左边的字符移动到最右边. 例如, 若 A = 'abcde',在移动一次之后结果就是'bcdea' .如果在若干次旋转 ...

  6. Java实现 LeetCode 792 自定义字符串排序(暴力)

    792. 匹配子序列的单词数 给定字符串 S 和单词字典 words, 求 words[i] 中是 S 的子序列的单词个数. 示例: 输入: S = "abcde" words = ...

  7. Java实现 LeetCode 791 自定义字符串排序(桶排序)

    791. 自定义字符串排序 字符串S和 T 只包含小写字符.在S中,所有字符只会出现一次. S 已经根据某种规则进行了排序.我们要根据S中的字符顺序对T进行排序.更具体地说,如果S中x在y之前出现,那 ...

  8. Java实现 LeetCode 767 重构字符串(ASCII的转换)

    767. 重构字符串 给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同. 若可行,输出任意可行的结果.若不可行,返回空字符串. 示例 1: 输入: S = "aab&qu ...

  9. Java实现 LeetCode 541 反转字符串 II(暴力大法)

    541. 反转字符串 II 给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转.如果剩余少于 k 个字符,则将剩余的所有全部反转.如果有小于 2k 但大于或 ...

随机推荐

  1. Mysql常用sql语句(21)- regexp 正则表达式查询

    测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 前言 正则的强大不言而喻,Mysql中也提供了 reg ...

  2. Mysql 常用语句实战(3)

    前置 sql 语句 用来创建表.插入数据 ; DROP TABLE IF EXISTS dept_;-- 部门表 DROP TABLE IF EXISTS emp_;-- 部门表 ; SELECT @ ...

  3. 未联网下,在eclipse中编辑xml文件如何自动提示设置

    断网情况下,用eclipse编辑xml文件如何自动提示? 以编辑hibernate中的xml为例: 首先,我们都知道xml提示是引用.dtd文件的. 1.复制这个dtd路径,设置eclipse属性,搜 ...

  4. 自定义docker的镜像

  5. 判断数组的方法/判断JS数据类型的四种方法

    参考文: 以下 3 个判断数组的方法,请分别介绍它们之间的区别和优劣Object.prototype.toString.call() . instanceof 以及 Array.isArray() h ...

  6. MySQL(5)— 常用函数

    五.MySQL常用函数 可参考[官网文档]https://dev.mysql.com/doc/refman/8.0/en/ 5-1.基本函数 数学运算: -- 数学运算 SELECT ABS(-8) ...

  7. EventBus/EventQueue 再思考

    EventBus/EventQueue 再思考 Intro 之前写过两篇文章,造轮子系列的 EventBus/EventQueue,回想起来觉得当前的想法有点问题,当时对 EvenStore 可能有点 ...

  8. SQL——模糊查询LIKE

    LIKE操作符 - 用于WHERE子句中搜索列中指定模式.    语法:SELECT columnName(s) FROM tableName WHERE columnName LIKE patter ...

  9. JS中Class的两种写法

    写法一:使用函数: var ClassName = function() { this.message = 'dat.gui'; this.speed = 0.8; this.displayOutli ...

  10. mantisbt2.22.1 中使用自带的phpmailer发送邮件(实测可用)

    mantis最新版本安装无难度,直接集成LAMP环境,解压放到web目录下运行,按界面显示一步步操作. 1.前提默认已安装好mantis,自带phpmailer的路径为:mantisbt2/vendo ...