LeetCode第87題(擾亂字串)
原題如下:
給定一個字串 s1,我們可以把它遞迴地分割成兩個非空子字串,從而將其表示為二叉樹。
下圖是字串 s1 = “great” 的一種可能的表示形式。
great
/ gr eat / \ / g r e at / a t 在擾亂這個字串的過程中,我們可以挑選任何一個非葉節點,然後交換它的兩個子節點。
例如,如果我們挑選非葉節點 “gr” ,交換它的兩個子節點,將會產生擾亂字串 “rgeat” 。
rgeat
/ rg eat / \ / r g e at / a t 我們將 "rgeat” 稱作 “great” 的一個擾亂字串。
同樣地,如果我們繼續將其節點 “eat” 和 “at” 進行交換,將會產生另一個新的擾亂字串 “rgtae” 。
rgtae
/ rg tae / \ / r g ta e / t a 我們將 "rgtae” 稱作 “great” 的一個擾亂字串。
給出兩個長度相等的字串 s1 和 s2,判斷 s2 是否是 s1 的擾亂字串。
示例 1:
輸入: s1 = “great”, s2 = “rgeat” 輸出: true 示例 2:
輸入: s1 = “abcde”, s2 = “caebd” 輸出: false
這道題確實是比較坑的,因為他打上了動態規劃的標籤,但是說實話 ,我連最優子結構 都找不到。。。所以只能另尋它路,同時你需要注意題中的一句話!!!“我們可以挑選任何一個非葉節點,然後交換它的兩個子節點”
根據上面的提示 一般都可以很快的寫出答案來,但是!!!!!!!你會發現時間複雜度達不到!!!(這個時候 你需要有以下思考, 1.我是否做了很多無用功(讓計算機計算了根本就沒有必要的部分) 2.如果1中我沒有做無用功,那麼說明這個演算法本身就有問題,我需要想其他的方法) 經過仔細觀察,你會發現 如果 s1 被拆成 ge+rat s2 被拆成 eag +rt 的時候 其實根本就沒有必要 去比較 rt是否是 ge的擾亂字串了!!!!!!直接就return false
程式碼如下:
vector<int> str_hash(string &s){
vector<int>m(30); for (int i = 0; i <= m.size() - 1; i++)m[i] = 0;
for (int i = 0; i <= s.size() - 1; i++){
m[s[i] - 'a']++;
}
return m;
}
bool bijiao(vector<int>&a, vector<int>&b){
if (a.size() != b.size())return false;
for (int i = 0; i <= a.size() - 1; i++){
if (a[i] != b[i])return false;
}
return true;
}
bool isScramble(string &s1, string &s2) {
if (s1.size() <= 0 || s2.size() <= 0) return false;
if (s1.size() <= 1){
if (s1[0] == s2[0])
return true;
else return false;
}
vector<int>s1_hash = str_hash(s1);
vector<int>s2_hash = str_hash(s2);
if (bijiao(s1_hash, s2_hash) == false) return false;
for (int size = 1; size <= s2.size() - 1; size++){
string s2_x = s2.substr(0, size), s2_y = s2.substr(size, s2.size() - size);
string s1_x = s1.substr(0, size), s1_y = s1.substr(size, s1.size() - size);
if (isScramble(s1_x, s2_x) && isScramble(s1_y, s2_y)) return true;
else {
s1_x = s1.substr(s1.size() - size, size); s1_y = s1.substr(0, s1.size() - size);
if (isScramble(s1_x, s2_x) && isScramble(s1_y, s2_y)) return true;
}
}
return false;
}