- 鏈接 : 最小覆蓋子串
- 題意:給定一個字符串s以及t,判斷 s 裏包含 t 所有字母的最小子串。
- 思路:雙指針的應用——滑動窗口
(官方題解)舉個例子,S = “ABAACBAB”,T = “ABC”
首先兩個指針 left = right = 0
然後right 逐漸增加,直到窗口包含t 所有字母
這時,維護最小的窗口,所以逐漸 縮減窗口,left ++ 。如果窗口減小後,不滿足條件,則right++。
- 代碼:
註釋我寫的很詳細
class Solution {
public:
string minWindow(string s, string t) {
//need是 t包含的字母, window是滑動窗口
unordered_map<char,int> need, window;
for(char c : t) need[c] ++;
//left,right是窗口
//valid 是判斷滿足條件與否,window內每有一個t內的字母,valid++
int left = 0, right = 0, valid = 0;
int start = 0, len = INT_MAX;
while(right < s.size()){
//每次窗口滑動
char tmp = s[right];
right ++;
//t中所有tmp,window內都有,則valid++
if(need.count(tmp)){
window[tmp] ++;
if(window[tmp] == need[tmp]){
valid ++;
}
}
//窗口內包含t內所有字母
while(valid == need.size()){
//每次更新最小窗口。start和len是確定最後子串的。
//left和right最後不一定是最小窗口
if(right - left < len){
start = left;
len = right - left;
}
//滿足條件後窗口縮減
char d = s[left];
left ++;
//縮減後丟失的字母在t中出現,且丟失後不滿足條件。
if(need.count(d)){
if(window[d] == need[d]){
valid --;
}
window[d] --;
}
}
}
return len == INT_MAX ? "" : s.substr(start,len);
}
};
-
遇到的問題:
1、今天另外一道題所學到的知識:
vector< int > a(n) 。 用此種方法構造vector的長度,這樣可以直接 cin>>a[i]2、文件流輸入輸出
#define _DEBUG
#ifdef _DEBUG
freopen(“in.txt”,“r”,stdin);
freopen(“out.txt”,“w”,stdout);
#endif此結構是 #ifdef 標識符 ***** #endif
如果define了標識符,那麼裏面的部分就會編譯運行,否則不會。
如上, #define _DEBUG,則freopen兩行可以編譯運行。提交的時候只需要註釋掉宏定義的此句即可。3、INT_MAX 是頭文件 limit.h 裏的宏定義
因爲用INF的時候,以前都是用 0x7fffffff,就是int的最大值,除了符號位是0,其他都是1。
INT_MAX等於此值,可以直接使用。4、unordered_map
是無序的一個鍵值對集合。
map有個特性,即插入後自動按照 key的值進行排序,所以是有序的。性能上應該不如 unordered_map
聲明: unordered_map<char, int> mp;
主要方法基本和map一致。