【LeetCode】87. Scramble String【分治法】

把一個字符串變成一顆二叉樹,如果一個新字符串能由任意交換子樹得到,則稱爲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;

    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章