Topic: Hard
Question:
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.
» Solve this problem
Method:
1.Recursive--base case is two strings length is equal or not and whether the only char in these two string are the same. Once the length is bigger than 1, traverse the string which-ever, OK, find out the the substring with length i for two sides and make a letter comparison to see do they have the same letters in the string? If yes, go to next recursion to see whether the two sides of each string still have same substrings at the specific position.
2. DP-- 3 dimensional DP, oh my! But remember to ask this question: what do we remember? In this case, we remember the already compared substrings' situations. To be continued...
Code:
public class Solution {
public boolean isScramble(String s2, String s1) {
// Start typing your Java solution below
// DO NOT write main() function
if(s1.length() != s2.length()) return false;
else if(s1.length() == 1) return s1.charAt(0)==s2.charAt(0);
else{
for(int i=1; i<s2.length(); i++){
String a1 = s1.substring(0, i);
String a2 = s1.substring(i);
String b1 = s2.substring(0, i);
String b2 = s2.substring(i);
if(checkLetters(a1, b1)){
if(isScramble(a1, b1) && isScramble(a2, b2)){
return true;
}
}
b1 = s2.substring(0, a2.length());
b2 = s2.substring(a2.length());
if(checkLetters(a1, b2)){
if(isScramble(a1, b2) && isScramble(a2, b1)){
return true;
}
}
}
}
return false;
}
private boolean checkLetters(String s1, String s2){
int[] set = new int[256];
for(int i=0; i<s1.length(); i++)
set[s1.charAt(i)-'0']++;
for(int i=0; i<s2.length(); i++){
if(set[s2.charAt(i)-'0']-- == 0)
return false;
}
return true;
}
}
Code for DP:
boolean isScramble(String s1, String s2) {
if(s1.equals(s2))
return true;
boolean[][][] scrambled = new boolean[s1.length()][s2.length()][s1.length() + 1];
for(int i = 0; i < s1.length(); i++)
for(int j = 0; j < s2.length(); j++){
scrambled[i][j][0] = true;
scrambled[i][j][1] = s1.charAt(i) == s2.charAt(j);
}
for(int i = s1.length() - 1; i >= 0 ; i--)
for(int j = s2.length() - 1; j >= 0; j--)
for(int n = 2; n <= Math.min(s1.length() - i, s2.length() - j); n ++)
for(int m = 1; m < n; m++){
scrambled[i][j][n] |= scrambled[i][j][m] && scrambled[i + m][j + m][n - m] || scrambled[i][j + n - m][m] && scrambled[i + m][j][n - m];
if(scrambled[i][j][n]) break;
}
return scrambled[0][0][s1.length()];
}
Summary:
太难,不正常的一道面试题,DP运用了三维布尔数组存放已经比较过的scramble substring,解法依旧在研究中。