87. Scramble String - jiejackyzhang/leetcode-note GitHub Wiki

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.

##Approach 1: recursion 解题思路为recursion。

对于两个string s1和s2,若它们是scramble string,则在其中找一个断点i,满足:

(isScramble(s1[0:i], s2[0:i]) && isScramble(s1[i:],s2[i:]))
|| (isScramble(s1[0:i], s2[s2.len-i:]) && isScramble(s1[i:],s2[0,s2.len-i]))

这个过程可以一直递归下去。

public class Solution {
    public boolean isScramble(String s1, String s2) {
        if(s1 == null || s2 == null || s1.length() != s2.length()) return false;
        if(s1.equals("")) return false;
        if(s1.equals(s2)) return true;
        int[] letters = new int[26];
        for(int i = 0; i < s1.length(); i++) {
            letters[s1.charAt(i) - 'a']++;
            letters[s2.charAt(i) - 'a']--;
        }
        for(int i =0; i < 26; i++) {
            if(letters[i] != 0) return false;
        }
        for(int i = 1; i < s1.length(); i++) {
            if(isScramble(s1.substring(0,i), s2.substring(0,i)) 
                && isScramble(s1.substring(i), s2.substring(i))) return true;
            if(isScramble(s1.substring(0,i), s2.substring(s2.length()-i)) 
                && isScramble(s1.substring(i), s2.substring(0,s2.length()-i))) return true;
        }
        return false;
    }
}

##Approach 2: Dynamic Programming

public class Solution {
    public boolean isScramble(String s1, String s2) {
        int len = s1.length();
        if(len!=s2.length()) return false;
        if(len==0) return true;
        boolean[][][] isScr = new boolean[len][len][len];
        for(int i = 0; i < len; i++) { //length of current substring, 0 means length==1
            for(int j = 0; j + i < len; j++) { //start point of current substring at s1.
                for(int k = 0; k + i < len; k++) { //start point of current substring at s2.
                    if(i==0) isScr[i][j][k] = s1.charAt(j)==s2.charAt(k);
                    for(int m = 0; m < i; m++) {
                        if(isScr[m][j][k] && isScr[i-(m+1)][j+m+1][k+m+1]) isScr[i][j][k] = true;
                        else if(isScr[m][j][k+i-m] && isScr[i-(m+1)][j+m+1][k]) isScr[i][j][k] = true;
                    }
                }
            }
        }
        return isScr[len-1][0][0];
    }
}