[LeetCode] 87. 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.

Example 1:

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

Example 2:

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

扰乱字符串。题意是给一个string s1,这个string被表示成一个二叉树。在树的叶节点,每个字母会被分到二叉树的每一个最小的分支上自成一支。

如上例子,great和rgeat是互为scramble string的。这题给的tag是DP但是DP的实现是三维的,几乎不可能在面试过程中完美实现。这里我给出的是递归解法,比较直观。

时间O(n!) - 我其实不是很确定

空间O(n) - 因为递归用到栈空间

JavaScript实现

 1 /**
 2  * @param {string} s1
 3  * @param {string} s2
 4  * @return {boolean}
 5  */
 6 var isScramble = function(s1, s2) {
 7     if (s1 === s2) return true;
 8     const letters = new Array(128).fill(0);
 9     const a = 'a'.charCodeAt(0);
10     for (let i = 0; i < s1.length; i++) {
11         letters[s1.charCodeAt(i) - a]++;
12         letters[s2.charCodeAt(i) - a]--;
13     }
14     for (let i = 0; i < 128; i++) {
15         if (letters[i] !== 0) return false;
16     }
17     for (let i = 1; i < s1.length; i++) {
18         if (isScramble(s1.substring(0, i), s2.substring(0, i)) && isScramble(s1.substring(i), s2.substring(i)))
19             return true;
20         if (
21             isScramble(s1.substring(0, i), s2.substring(s2.length - i)) &&
22             isScramble(s1.substring(i), s2.substring(0, s2.length - i))
23         )
24             return true;
25     }
26     return false;
27 };

Java实现 - 超时

 1 class Solution {
 2     public boolean isScramble(String s1, String s2) {
 3         // corner case
 4         if (s1 == null || s2 == null) {
 5             return false;
 6         }
 7         if (s1.equals(s2)) {
 8             return true;
 9         }
10         // normal case
11         int[] letters = new int[26];
12         int len = s1.length();
13         for (int i = 0; i < len; i++) {
14             letters[s1.charAt(i) - 'a']++;
15             letters[s2.charAt(i) - 'a']--;
16         }
17         for (int i = 0; i < 26; i++) {
18             if (letters[i] != 0) {
19                 return false;
20             }
21         }
22         for (int i = 1; i < len; i++) {
23             if (isScramble(s1.substring(0, i), s2.substring(0, i)) && isScramble(s1.substring(i), s2.substring(i))) {
24                 return true;
25             }
26             if (isScramble(s1.substring(0, i), s2.substring(len - i)) && isScramble(s1.substring(i), s2.substring(0, len - i))) {
27                 return true;
28             }
29         }
30         return false;
31     }
32 }

Java另一种带memorization的实现

 1 class Solution {
 2     HashMap<String, Boolean> map = new HashMap<>();
 3 
 4     public boolean isScramble(String s1, String s2) {
 5         StringBuilder sb = new StringBuilder();
 6         sb.append(s1);
 7         sb.append(s2);
 8         String key = sb.toString();
 9 
10         if (map.containsKey(key)) {
11             return map.get(key);
12         }
13 
14         if (s1.equals(s2)) {
15             map.put(key, true);
16             return true;
17         }
18 
19         int[] letters = new int[26];
20         for (int i = 0; i < s1.length(); i++) {
21             letters[s1.charAt(i) - 'a']++;
22             letters[s2.charAt(i) - 'a']--;
23         }
24         for (int i = 0; i < 26; i++) {
25             if (letters[i] != 0) {
26                 map.put(key, false);
27                 return false;
28             }
29         }
30 
31         for (int i = 1; i < s1.length(); i++) {
32             if (isScramble(s1.substring(0, i), s2.substring(0, i)) && isScramble(s1.substring(i), s2.substring(i))) {
33                 map.put(key, true);
34                 return true;
35             }
36 
37             if (isScramble(s1.substring(0, i), s2.substring(s1.length() - i))
38                     && isScramble(s1.substring(i), s2.substring(0, s1.length() - i))) {
39                 map.put(key, true);
40                 return true;
41             }
42         }
43 
44         map.put(key, false);
45         return false;
46     }
47 }

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/11762580.html