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
题意:
对于一个字符串,若通过一些列树形颠倒(确定一点后,前后子串交换)得到一个新的字符串,则互为Scramble String
思路:
这道题面试很低频,因为若要dp解,则需三维dp,难度很高不适合面试
直接用递归,观察规律:
若s1 和 s2 长度都为1 : 两字符串必须完全相当
若s1 和 s2 长度都为2: 则当s1 = "ab"时, s2 = "ab" || "ba"
若s1 和 s2 长度都为3: 将 s1 分成 s1Left 和 s1Right两部分
s2 分成 s2Left 和 s2Right 两部分
则 ( s1Left isScrambled s2Left && s1Right isScrambled s2Right ) 或者 (s1Left isScrambled s2Right && s1Right isScrambled s2Left )
如图,
所以,
先判断s1和s2是否是valid anagram (变位词): 意味着两个字符串长度一致,互相只是各个字符串变换了位置
再递归生成s1的左边、右边,s2 的左边、右边
递归出口: s1等于s2 return true
代码:
1 class Solution { 2 public boolean isScramble(String s1, String s2) { 3 // corner 4 if(s1.length() != s2.length() || s1 == null || s2 == null) return false; 5 // recursion 出口 6 if(s1.equals(s2)) return true; // 一定要加,否则recursion 没有出口 7 // valid anagram or not 8 int[]map = new int[256]; 9 for(int i = 0; i < s1.length(); i++){ 10 map[s1.charAt(i)] ++; 11 map[s2.charAt(i)] --; 12 } 13 for(int i : map){ 14 if( i != 0){ 15 return false; 16 } 17 } 18 // recursion 19 for(int i = 1; i < s1.length(); i++){ 20 if(isScramble(s1.substring(0,i), s2.substring(0,i)) && isScramble(s1.substring(i), s2.substring(i))) return true; 21 if(isScramble(s1.substring(0,i), s2.substring(s2.length()-i)) && isScramble(s1.substring(i), s2.substring(0, s2.length()-i))) return true; 22 23 } 24 return false; 25 } 26 27 }