题目描述:
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 ifs2 is a scrambled string of s1.
这道题可以递归求解。每次递归时,首先判断:如果s1和s2相等,返回true。如果s1和s2的长度不等,返回false。接下来对s1的从1到s1.length() - 1的每一个划分点,对s1和s2做划分,递归的判断是否划分后的s1和s2的左右两部分都是scrambled string. 这个判断分两种情况,一种情况是s1划分后没有经过交换得到的s2,那么直接递归的判断划分后相对应的左右两半。还有一种情况,就是s1划分后,经过交换得到s2。在这种情况下,s1和s2的划分点需要互补,即如果s1在i划分,则s2在s2.length() - i处划分,然后递归的判断s1的左半与s2的右半和s1的右半与s2的左半。
在递归判断之前,可以做一个预判,如果s1和s2包含不同数目的字符,那么直接返回false。如果不做这个判断,大集合超时。
Java代码:
public boolean isScramble(String s1, String s2) {
// Start typing your Java solution below
// DO NOT write main() function
if (s1.equals(s2)) {
return true;
}
if (s1.length() != s2.length()) {
return false;
}
// Pruning
// If s1 and s2 contain different characters, return false.
int[] a = new int[256];
java.util.Arrays.fill(a, 0);
for (int i = 0; i < s1.length(); i++) {
char c = s1.charAt(i);
a[c - 'a']++;
}
for (int i = 0; i < s2.length(); i++) {
char c = s2.charAt(i);
a[c - 'a']--;
}
for (int i = 0; i < 256; i++) {
if (a[i] != 0) {
return false;
}
}
for (int i = 1; i < s1.length(); i++) {
String s1L = s1.substring(0, i);
String s1R = s1.substring(i);
String s2L = null;
String s2R = null;
s2L = s2.substring(0, i);
s2R = s2.substring(i);
if (isScramble(s1L, s2L) && isScramble(s1R, s2R)) {
return true;
}
s2L = s2.substring(0, s2.length() - i);
s2R = s2.substring(s2.length() - i);
if (isScramble(s1L, s2R) && isScramble(s1R, s2L)) {
return true;
}
}
return false;
}