先給題
給定兩個字串 s1 和 s2,寫乙個函式來判斷 s2 是否包含 s1 的排列。
換句話說,第乙個字串的排列之一是第二個字串的子串。
示例1:
輸入: s1 = "ab" s2 = "eidbaooo"
輸出: true
解釋: s2 包含 s1 的排列之一 ("ba").
示例2:
輸入: s1= "ab" s2 = "eidboaoo"
輸出: false
注意:輸入的字串只包含小寫字母
兩個字串的長度都在 [1, 10,000] 之間
今天第一次,沒有看題解做出來了,時間和記憶體還都可以的情況下。繼續加油!
以後就不談暴力破解了,一般這樣的題暴力破解都超時
說一說自己的想法
第一眼看到這個字串匹配的問題,就想到了滑動視窗(雙指標),最近做這樣的題蠻多的。
(看了題解才知道我用的是雙指標,雙指標和滑動視窗並不是一摸一樣的,具體區別可以看感覺講的蠻好的)
我們先來理解一下題,題的意思是我們要判斷s2中是否存在乙個與s1等長度的子陣列,元素種類與元素個數與s1完全相同。有就返回1,沒有就返回0.
(一開始我是按照順序也一致做的,不管正序或者逆序。但後來發現理解錯題了。)
所以,我們要想辦法來記錄一下子字串的的元素狀況,我們開闢乙個長度為26的陣列來記錄個元素的數量。這個陣列來記錄s1字串元素的情況。當右指標移動時,判斷這個元素個數是否為0,不為0代表目前子字串的元素種類和個數都沒問題,如果為0,就表明這個元素要麼不存在,要麼前面存在這個元素的數量已經超過了s1中的,這時候我們就要左指標移動,並且要再把左邊移動出來的元素再記錄進去。
那麼記下來的問題就是如何判斷查詢出符合的情況以及左指標根據什麼條件移動。(這也是最難的兩個點)
左指標一旦移動,就代表了當前子字串的元素種類或者數目不符合要求,左指標需要移動,那麼左指標移動到什麼地步,子字串就符合了?
極限的情況,我們遇到了乙個s1根本不存在的元素,那麼此時子字串肯定不符合要求了,讓left和right移動到這個元素的後面重新開始。
而如果我們遇到的元素是前面出現的元素,只是數量達不到要求,那麼左指標只要移動到與該元素相同的那個元素的後面,我們就可以不用再移動了,此時子字串肯定符合要求。
根據上面的兩種情況,我們可以得出,只要右指標指向的元素的可用值為0,我們左指標就要一直移動,直到左指標達到右指標的位置。當左指標不再移動時,再來判斷右指標指向元素是否大於0(因為右指標指向的元素不存在,那麼左指標就移動到右指標的位置,所以還需要在判斷一下數值),大於0,就說明這個元素是存在於s1的,記錄像響值,=0,就說明這個元素不存在,左指標繼續移動一位,跳過這個元素。
一開始我是這麼想的,當這個記錄數值的26位陣列所有值都為0的時候,就代表著元素全部用完了,但這樣太費時了。
所以我們來找另一種判斷的方法。
假設一開始我們就沒遇到不符合的元素,那麼右指標一直移動,當這個子陣列元素情況與s1相等時,此時我們就可以判斷它是符合條件的。這樣的話如果我們遇到不符合的元素,那麼此時右指標減去左指標+1 一定是小於等於s1的長度的。
根據上述假設,我們就可以知道,當判斷後如果右指標減去左指標+1(即當前子陣列長度)達到了s1的長度,那麼我們就可以說存在符合題意的子陣列了。
classview codesolution
if (v[(int)s2[right] - 97] > 0
) v[(
int)s2[right] - 97]--;
else
left++;
}right++;
if (right - left ==s1.length())
return1;
}return0;
}};
題解有兩種,一種是滑動視窗,一種是雙指標(和我想的一摸一樣),所以在這裡我們就來說滑動視窗。
其實思路差不很多,我們依然是開闢陣列來記錄元素的狀況。只不過這次我們是來記錄兩個子陣列的情況。
要想符合題意,s2的子陣列長度肯定是s1的長度,所以只要兩個陣列的元素情況相同,我們就可以返回1。左指標跟著右指標移動,視窗的長度固定不變。
官方題解還對這個方法進行了優化,我們可以只開闢乙個陣列來記錄情況,這個陣列用來記錄上述方法中用來記錄元素狀況的兩個陣列的差,判斷條件我們可以用乙個diff來記錄他們的不同值,當差不為0,就讓diff++,只要diff不為0,那麼就不符合。
這是未優化的
1view codeclass
solution
8 vector cnt1(26), cnt2(26);9
for (int i = 0; i < n; ++i)
13if (cnt1 ==cnt2)
16for (int i = n; i < m; ++i) 22}
23return
false;24
}25 };
這是優化的
1view codeclass
solution
8 vector cnt(26);9
for (int i = 0; i < n; ++i)
13int diff = 0;14
for (int
c: cnt) 18}
19if (diff == 0
) 22
for (int i = n; i < m; ++i)
27if (cnt[x] == 0
) 30 ++cnt[x];
31if (cnt[x] == 0
) 34
if (cnt[y] == 0
) 37 --cnt[y];
38if (cnt[y] == 0
) 41
if (diff == 0
) 44}45
return
false;46
}47 };
想詳細了解的可以去這裡
字串排列
在網上看到了乙個操作字串的題目,該題為 字串排列。大概意思是列出字串中所有字元的所有組合並且輸出無重複。自己做了一下,這裡分享該題的思路,和做法。自我覺得實現的有些麻煩 歡迎指點。問題輸入乙個字串,列印出該字串中字元的所有排列。輸入 字串abc。輸出 列印出由字元a,b,c所能排列出來的所有字串ab...
字串排列
輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。第一種方法 字串拼接 function permutate str else return result console.log pe...
字串的排列
題目 輸入乙個字串,列印出該字串中字元的所有排列。例如輸入字串 abc,則輸出由字元a b c所能排列出來的所有字串 abc acb bac bca cab和 cba。分析 這是一道很好的考查對遞迴理解的程式設計題,因此在過去一年中頻繁出現在各大公司的面試 筆試題中。我們以三個字元 abc為例來分析...