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.
解答:
1. Brute Force 递归。
基本的思想就是:在S1上找到一个切割点,左边长度为i, 右边长为len - i。 有2种情况表明它们是IsScramble
(1). S1的左边和S2的左边是IsScramble, S1的右边和S2的右边是IsScramble
(2). S1的左边和S2的右边是IsScramble, S1的右边和S2的左边是IsScramble (实际上是交换了S1的左右子树)
而i的取值可以是1 ~ len-1。 基于这个思想,我们可以写出以下的递归Brute Force 解:
引自stellari对复杂度的解释:
看了你的不少文章,感觉收获良多!只是有点小问题想请教:按照我的理解,那个递归算法在最差情况下应该是O(3^n),而非O(n^2)。理由是:假设函数运行时间为f(n),那么由于在每次函数调用中都要考虑1~n之间的所有长度,并且正反都要检查,所以有
f(n) = 2[f(1) + f(n-1)] +2[f(2) + f(n-2)] … + 2[f(n/2) + f(n/2+1)]. 易推得f(n+1) = 3(fn), 故f(n) = O(3^n)。当然这是最差情况下的时间复杂度。那么你提到的O(n^2),是否是通过其他数学方法得到的更tight的上限?欢迎探讨!
这一个解是不能通过LeetCode的检查的,复杂度是 3^N
1 public static boolean isScramble1(String s1, String s2) { 2 if (s1 == null || s2 == null) { 3 return false; 4 } 5 6 int len1 = s1.length(); 7 int len2 = s2.length(); 8 9 // the two strings should be the same length. 10 if (len1 != len2) { 11 return false; 12 } 13 14 return rec(s1, s2); 15 } 16 17 // Solution 1: The recursion version. 18 public static boolean rec1(String s1, String s2) { 19 int len = s1.length(); 20 21 // the base case. 22 if (len == 1) { 23 return s1.equals(s2); 24 } 25 26 // 鍒掑垎2涓瓧绗︿覆 27 for (int i = 1; i < len; i++) { 28 // we have two situation; 29 // the left-left right-right & left-right right-left 30 if (rec1(s1.substring(0, i), s2.substring(0, i)) 31 && rec1(s1.substring(i, len), s2.substring(i, len))) { 32 return true; 33 } 34 35 if (rec1(s1.substring(0, i), s2.substring(len - i, len)) 36 && rec1(s1.substring(i, len), s2.substring(0, len - i))) { 37 return true; 38 } 39 } 40 41 return false; 42 }