把一個字符串變成一顆二叉樹,如果一個新字符串能由任意交換子樹得到,則稱爲Scramble String。苦思冥想,自知不善於分治,故特別記錄下來。
如果兩個字符串是Scramble String,則必然有它們的兩個子串分別互爲Scramble String,如此二分下去直到字串長度爲1,就只需判斷是否相等。能有這種分而治之的思想此題就非常簡單了。
for (int i = 1; i < n; ++i) {
if ((isScramble(s1.substr(0, i), s2.substr(0, i)) && isScramble(s1.substr(i), s2.substr(i))) || (isScramble(s1.substr(0, i), s2.substr(n - i)) && isScramble(s1.substr(i), s2.substr(0, n - i)))) {
return true;
}
}
以上核心代碼非常簡單易懂,只需要窮舉所有的字串。但是這樣簡單窮舉會遇到超時的問題,還要藉助一些輔助判斷先排除掉某些根本不可能的情況,減少遞歸窮舉的次數。比如,如果兩個字符串長度不相等就必定不是 Scramble String,字母種類和數量不相等也不是Scramble String。以下是完整C++代碼。
class Solution {
public:
bool isScramble(string s1, string s2) {
if (s1 == s2) return true;
if (s1.size() != s2.size()) return false;
int n = s1.size(), m[26] = {0};
for (int i = 0; i < n; i++) {
m[s1[i] - 'a']++;
m[s2[i] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (m[i] != 0) return false;
}
for (int i = 1; i < n; i++) {
if ((isScramble(s1.substr(0, i), s2.substr(0, i)) && isScramble(s1.substr(i), s2.substr(i))) || (isScramble(s1.substr(0, i), s2.substr(n - i)) && isScramble(s1.substr(i), s2.substr(0, n - i)))) {
return true;
}
}
return false;
}
};