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.


1.我的解答  好不容易寫成功的哇哇~~   最後還是超時了。。。。淚崩~~~

要對s1進行改變,然後判斷s2是否存在於s1的變換集合中

我的想法就是,對字符串進行依次個切分,然後把兩部分進行遞歸交換,把交換的都存在集合裏,最後組合起來看看是不是跟s2是否相等。

比如 abcd 依次劃分爲a,bcd   ab,cd  abc,d

然後依次對各個部分遞歸

用dfs??  同時記下來每個狀態的變換,用記憶化搜索方法

class Solution {
public:
    void solve(string s, map<string,set<string>>& sets){
        map<string,set<string>> s1, s2;
        if(s.size() == 1){
            if(sets.find(s) == sets.end())
                sets[s].insert(s);
            return;
        }
        if(sets.find(s) != sets.end())
            return;
        else
            sets[s].insert(s);  //這裏注意下,要把s本身也加入進去
            
        for(int i = 0; i < s.size()-1; i++){
            string p1 = s.substr(0,i+1);
            string p2 = s.substr(i+1);
            solve(p1,s1);
            solve(p2,s2);
            for(set<string>::iterator it = s1[p1].begin(); it != s1[p1].end(); it++){
                for(set<string>::iterator is = s2[p2].begin(); is != s2[p2].end(); is++){
                    string t = *it + *is;  //這裏也要注意下,交換和不交換都要記錄進去 如 a+f(bc)
                    sets[s].insert(t);
                    t = *is + *it;  // f(bc)+a
                    sets[s].insert(t);
                }
            }
        }
        
    }

    bool isScramble(string s1, string s2) {
        if(s1.size() != s2.size() || s1.size() == 0 || s2.size() == 0) return false;
        if(s1.size() == 1){
            if(s1[0] == s2[0]) 
                return true;
            else
                return false;
        } 
        map<string,set<string>> sets;
        solve(s1, sets);
        for(set<string>::iterator it = sets[s1].begin(); it != sets[s1].end(); it++){
            if(*it == s2)
            return true;
        }
        return false;
    }
};

2. 用動態規劃的方法

大神真是天才啊啊啊

解題思路: 因爲這道題根本就是對s1進行中間某段的切分,因此只要從1~n-1的切分點進行遍歷,然後比較s1是前i個部分和s2的前i個部分(當然還有對應的後n-i個的部分),這種情況下的對應上呢? 

還是s2的後i個部分和s1的前i個部分對應上呢? 這種情況就是對s1的第i個點進行旋轉了。

同時在比較以上步驟之前,先判斷s1 s2兩部分是否字母都相同,如果不同就直接返回false

注意點: 這裏我漏了一個,就是如果s1==s2,直接就return true; 無需再進行比較;這也避免了出現空串和單個字母的情況的出現的處理了、


以下是代碼:

class Solution {
public:
    bool equals(string s1, string s2){//判斷s1和s2中的字母是否都相同,這是最基本的判斷
        int c[26];
        memset(c, 0, sizeof(c));
        for(int i = 0; i < s1.size(); i++)
            c[s1[i] - 'a']++;
        for(int i = 0; i < s2.size(); i++){
            c[s2[i] - 'a']--;
            if(c[s2[i] - 'a'] < 0)
            return false;
        }
        return true;
    }

    bool isScramble(string s1, string s2) {
        if(s1.size() != s2.size()) return false;
        int n = s1.size();
        if(s1 == s2) return true;
        if(equals(s1, s2)){
            for(int i = 1; i < s1.size(); i++){ //這個是個數
                string s11 = s1.substr(0,i); //s1的前i個數
                string s12 = s1.substr(i); //s1的後n-i個數
                string s21 = s2.substr(0,i); //s2的前i個數
                string s22 = s2.substr(i); //s2的後n-i個數
                string s23 = s2.substr(n-i); //s2的後i個數
                string s24 = s2.substr(0,n-i); //s2的後n-i個數
                if(isScramble(s11,s21) && isScramble(s12,s22)) 
                //假如是對s1沒有旋轉,就把s1,s2 對應的第i部分切開的前i個和後n-i個進行比較
                    return true;
                if(isScramble(s11, s23) && isScramble(s12, s24)) //假如對s1進行旋轉,就把s1的前i個和s2的後i個進行比較
                    return true;
            }
        }
        return false;
    }
};


發佈了171 篇原創文章 · 獲贊 7 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章