原题网址:https://leetcode.com/problems/scramble-string/
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 {
private int[] frequency(char[] sa, int from, int to) {
int[] f = new int[26];
for(int i=from; i<=to; i++) {
f[sa[i]-'a'] ++;
}
return f;
}
private boolean equalFrequency(int[] f1, int[] f2) {
for(int i=0; i<f1.length; i++) {
if (f1[i] != f2[i]) return false;
}
return true;
}
private boolean scramble(char[] sa1, int f1, int t1, char[] sa2, int f2, int t2) {
if (t1 - f1 != t2 - f2) return false;
if (f1>t1) return false;
if (f1==t1) return sa1[f1] == sa2[f2];
int[] c1 = frequency(sa1, f1, t1);
int[] c2 = frequency(sa2, f2, t2);
if (!equalFrequency(c1, c2)) return false;
for(int i=0; i<t1-f1; i++) {
if (scramble(sa1, f1, f1+i, sa2, f2, f2+i) && scramble(sa1, f1+i+1, t1, sa2, f2+i+1, t2)) return true;
if (scramble(sa1, f1, f1+i, sa2, t2-i, t2) && scramble(sa1, f1+i+1, t1, sa2, f2, t2-i-1)) return true;
}
return false;
}
public boolean isScramble(String s1, String s2) {
char[] sa1 = s1.toCharArray();
char[] sa2 = s2.toCharArray();
return scramble(sa1, 0, sa1.length-1, sa2, 0, sa2.length-1);
}
}