Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great"
:
great / \ gr eat / \ / \ g r e at / \ a t
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node "gr"
and swap its two children, it produces a scrambled string "rgeat"
.
rgeat / \ rg eat / \ / \ r g e at / \ a t
We say that "rgeat"
is a scrambled string of "great"
.
Similarly, if we continue to swap the children of nodes "eat"
and "at"
, it produces a scrambled string "rgtae"
.
rgtae / \ rg tae / \ / \ r g ta e / \ t a
We say that "rgtae"
is a scrambled string of "great"
.
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
public class Solution {
public boolean isScramble(String s1, String s2) {
char[] t1 = s1.toCharArray();
char[] t2 = s2.toCharArray();
if (t1.length != t2.length) return false;
return scramble(t1, 0, t2, 0, t2.length);
}
//此方法做出来一下这几点的优化方案:
//用 字符数组和长度来替代字符串不用每次都切割子串
// 在判断字符的数组中的元素是否相同的时候少了一个对letter的循环遍历
private boolean scramble(char[] s1, int i, char[] s2, int j, int n) {
//当 n == 1 的时候应该向上回溯
if (n == 1) return s1[i] == s2[j];
//判断字符是否相等
int[] letter = new int[26];
for (int k = i; k < i+n; k++) {
++letter[s1[k]-'a'];
}
for (int k = j; k < j+n; k++) {
//存在不想等的字符
if (--letter[s2[k]-'a'] < 0)
return false;
}
for (int l = 1; l < n; l++) {
//将字符数组的前半部分和后半部分分别的进行对比 相当于s.substring()
if (scramble(s1,i,s2,j,l)
&& scramble(s1,i+l,s2,j+l,n-l)) return true;
//将s1前半部分和s2的后半部分对比,
if (scramble(s1,i,s2,n+j-l,l)
&& scramble(s1,i+l,s2,j,n-l)) return true;
}
return false;
}
}