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 tTo 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 tWe 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 aWe 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.
A:
首先,我们想到的是递归调用
代码如下:
public class Solution { public boolean isScramble(String s1, String s2) { // idea: assume s1 is original string , and s2 is the scrambled one // if scrambled, it must be that it is first k letters of s2 is the // scramble of first k letters of s1 if(s1.length() != s2.length()) return false; if(s1.length() == 1){ return s1.charAt(0) == s2.charAt(0); } for(int i = 1;i< s1.length()-1; i++){ // i is the position , belongs to left part boolean left1 = isScramble(s1.substring(0,i+1),s2.substring(0,i+1)); boolean right1 = isScramble(s1.substring(i+1),s2.substring(i+1)); boolean left2 = isScramble(s1.substring(0,i+1),s2.substring(s2.length() - i)); boolean right2 = isScramble(s1.substring(s1.length() - i),s2.substring(0,i+1)); if(left1 && right1 || left2 && right2) return true; } return false; } }
当然,结果是太慢 TLE
-----------下面是非递归的方法。 ------------------
主要错误在于: 对每个position, 我们有两个选择, 或者在这个点scramble或者在这里继续向两边分。
public class ScrambleString { public boolean isScramble(String s1, String s2) { // idea: assume s1 is original string , and s2 is the scrambled one // if scrambled, it must be that it is first k letters of s2 is the // scramble of first k letters of s1 if (s1.length() != s2.length()) return false; if (s1.length() == 1) { // s2.length == 1 if (s1.equals(s2)) { return true; } else { return false; } } // NOW string length >= 1 int n = s1.length(); // for the first k letters, check it is the left scramble. if (s1.equals(s2)) { return true; } // find a split at split index i // At position i, we have two choice, // 1) permute here, // 2) continue split at i, left to left, right to right for (int i = 1; i < s1.length(); i++) {// left and right should not // be empty // CASE 1: we scramble at this position // if left of s1 == right of s2, they are the same, we can return // true String s1LeftI = s1.substring(0, i); String s1AfterI = s1.substring( i); // if left of s1 is the same with right of s2, and vice versa String s2MatchLeftS1 = s2.substring(n - i); String s2MatchRightS1 = s2.substring(0, n - i); if (isPermuation(s1LeftI, s2MatchLeftS1)&& isPermuation(s1AfterI, s2MatchRightS1)) { boolean left = isScramble(s1LeftI, s2MatchLeftS1); boolean right = isScramble(s1AfterI, s2MatchRightS1); if (left && right) { return true; } } String s2LeftI = s2.substring(0, i); String s2AfterI = s2.substring( i); if (isPermuation(s1LeftI, s2LeftI)&& isPermuation(s1AfterI, s2AfterI)) { // if left of s1 is permuation of ( left of s2), and boolean left = isScramble(s1LeftI, s2LeftI); boolean right = isScramble(s1AfterI, s2AfterI); if (left && right) { return true; } } } return false; } private boolean isPermuation(String str1, String str2) { char[] a = str1.toCharArray(); char[] b = str2.toCharArray(); Arrays.sort(a); Arrays.sort(b); return Arrays.equals(a,b); } }
Mistakes:
1: 光顾的左右分区了,没有考虑,交换过来的情况。
2: 自己的命名挺ugly的。呵呵
Learned:
1: java 中, Arrays.sort()是基于int (或者double)类型的 quicksort实现。
因此,char [] 也可以直接调用,
--------------------------------第二遍-----------思想同上--------
public class Solution { public boolean isScramble(String s1, String s2) { // idea: assume s1 is original string , and s2 is the scrambled one // if scrambled, it must be that it is first k letters of s2 is the // scramble of first k letters of s1 if (s1.length() != s2.length()) return false; if (s1.length() == 1) { return s1.charAt(0) == s2.charAt(0); } char[] ch1 = s1.toCharArray(); char[] ch2 = s2.toCharArray(); Arrays.sort(ch1); Arrays.sort(ch2); // check whether ch1 == ch2 if(Arrays.equals(ch1,ch2)==false) return false; // now, characters are the same, we check their scrambling for (int leftLen = 1; leftLen < s1.length(); leftLen++) { // i is the length of left // part of s1 String leftS1 = s1.substring(0, leftLen ); String rightS1 = s1.substring(leftLen ); // if left i part match s1 String leftS2 = s2.substring(0, leftLen); String rightS2 = s2.substring(leftLen ); if (isScramble(leftS1, leftS2) && isScramble(rightS1, rightS2)) return true; // now test case 2, where s2 is scrambled to the right part String s2MatchLeftS1 = s2.substring(s2.length() - leftLen); String s2MatchRightS2 = s2.substring(0, s2.length() - leftLen); if (isScramble(leftS1, s2MatchLeftS1) && isScramble(rightS1, s2MatchRightS2)) return true; } return false; } }------------------------------3 rd -----------------思路同第二遍----------------
Error:
1: 很傻比, 不知道,s1的左边要跟s2的右边比较, 反而去左边和左边比较,右边和右边比较去了。 哎,SB
2: 脑子被驴踢了,哎,竟然能犯这个SB 错误。 自己看看吧。 为什么下面这样写不对。
import java.util.Arrays;
public class Solution {
public boolean isScramble(String s1, String s2) {
// use recursive idea, but instead of trying every possible chars,
if (s1.length() != s2.length())
return false;
int n = s1.length();
if (n == 0 || s1.equals(s2))
return true;
// now beginning and end is not equal, we need do left right matching
for (int i = 1; i < n; i++) {
String s1Left = s1.substring(0, i);
String s1Right = s1.substring(i);
// test whether left of s1 equals left of s2
String s2Left = s2.substring(0, i);
String s2Right = s2.substring(i);
if (isEqualAfterSort(s1Left, s2Left))
return isScramble(s1Left, s2Left)
&& isScramble(s1Right, s2Right);
s2Left = s2.substring(0, n - i);
s2Right = s2.substring(n - i);
// if left of s1 equals to right of s2
if (isEqualAfterSort(s1Left, s2Right))
return isScramble(s1Left, s2Right)
&& isScramble(s1Right, s2Left);
}
return false;
}
private boolean isEqualAfterSort(String str1, String str2) {
char[] arr1 = str1.toCharArray();
char[] arr2 = str2.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
String ss1 = new String(arr1);
String ss2 = new String(arr2);
return ss1.equals(ss2);
}
}
揭示错误2: 因为,即使两个sort后是一样的,但依然不能保证是scramble的。 因此,不能直接返回结果, 而应该是match之后,如果是true,才能返回
No comments:
Post a Comment