87. Scramble String

Description

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":

image.png

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".

image.png

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".

image.png

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.

Example 1:

Input: s1 = "great", s2 = "rgeat"
Output: true

Example 2:

Input: s1 = "abcde", s2 = "caebd"
Output: false

Solution

Recursion

这道题还是比较好理解的,将string表示成一棵树的形状,然后迭代交换non-leaf节点的两个子节点,看是否能得到另外一个string。

需要注意的是,题目中的树构造方式只是一个例子,"we may represent it as a binary tree by partitioning it to two non-empty substrings recursively."指的是我们可以将string按照任何比例分开。假设string s的长度为5,我们可以将其分成(1, 4), (2, 3), (3, 2), (4, 1)这几种方式。

class Solution {
    public boolean isScramble(String s1, String s2) {
        if (s1 == null || s2 == null || s1.length() != s2.length() || s1.isEmpty()) {
            return false;
        }
        
        return isScrambleRecur(s1, s2);
    }
    
    public boolean isScrambleRecur(String s1, String s2) {
        if (s1.equals(s2)) {
            return true;
        }
        // calculate character freq in advance to prune
        Map map = new HashMap<>();
        for (int i = 0; i < s1.length(); ++i) {
            char c = s1.charAt(i);
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        
        for (int i = 0; i < s2.length(); ++i) {
            char c = s2.charAt(i);
            if (map.getOrDefault(c, 0) == 0) {
                return false;
            }
            map.put(c, map.get(c) - 1);
        }
        
        int len = s1.length();
        for (int l = 1; l < s1.length(); ++l) {
            if ((isScrambleRecur(s1.substring(0, l), s2.substring(0, l)) 
                    && isScrambleRecur(s1.substring(l), s2.substring(l))) 
                || (isScrambleRecur(s1.substring(0, l), s2.substring(len - l)) 
                    && isScrambleRecur(s1.substring(l), s2.substring(0, len - l)))) {
                return true;
            }
        }
        
        return false;
    }
}

你可能感兴趣的:(87. Scramble String)