題目描述:c++
題解:spa
滑動窗口思想:用 i, j 表示滑動窗口的左邊界和右邊界,經過改變i,j來擴展和收縮滑動窗口,能夠想象成一個窗口在字符串上游走,code
當這個窗口包含的元素知足條件,即包含字符串T的全部元素,記錄下這個滑動窗口的長度j-i+1 和 窗口其實位置 i ,這些長度中的最小值blog
對應的子串 就是要求的結果。設置一個變量 cnt 記錄 滑動窗口中字符串
擴展滑動窗口 :向右 右邊界移動 j 直到 窗口中的子串剛好覆蓋 t 中全部字符時中止。(從不覆蓋到覆蓋)string
收縮滑動窗口: 向右移動左邊界 i 直到 窗口中的子串剛好覆蓋 t 中全部字符時中止。(再移動一步就再也不覆蓋,此時保存最小子串)it
代碼:io
1 #include <bits/stdc++.h> 2 using namespace std; 3 class Solution { 4 public: 5 string minWindow(string s, string t) 6 { 7 unordered_map<char,int> need;//記錄 字符串t中的字符和出現的次數 8 unordered_map<char,int> window;// 記錄滑動窗口內的字符和出現的次數 9 for(int i = 0; i < t.size();++i) 10 { 11 need[t[i]]++; 12 } 13 const int t_cnt = need.size(); 14 int start = 0;//s中包含t中全部字符的最短子串起始下標 15 int len = INT_MAX;//最短子串長度 16 int cnt = 0;//t中的字符 在滑動窗口中已完備存在的個數 17 int left = 0,right = 0;//滑動窗口左右邊界 18 char c = ' '; 19 while (right < s.size()) 20 { 21 //移動 right 擴大窗口,到窗口中的子串剛好覆蓋 t 中全部字符時中止 22 while (cnt < t_cnt && right < s.size()) 23 { 24 c = s[right]; 25 if(need.find(c) != need.end()) 26 { 27 if(++window[c] == need[c]) 28 { 29 ++cnt; 30 } 31 } 32 ++right; 33 } 34 //right 移動到最右,滑動窗口內的子串仍然沒有覆蓋t中全部字符,直接返回以前獲得的最小覆蓋子串 35 if(right == s.size() && cnt < t_cnt) 36 { 37 return len == INT_MAX?"":s.substr(start,len); 38 } 39 //移動left,收縮窗口,到窗口內的子串剛好覆蓋 t 中全部字符時中止(再收縮一步就再也不覆蓋了) 40 while(left < right && cnt == t_cnt) 41 { 42 c = s[left]; 43 if(need.find(c) != need.end()) 44 { 45 if(window[c]-- == need[c]) 46 { 47 --cnt; 48 } 49 } 50 ++left; 51 } 52 //此時的最小覆蓋子串的範圍應該是 [left-1,right-1] 53 if(right - left + 1 < len ) 54 { 55 start = left - 1; 56 len = right - left + 1; 57 } 58 } 59 return len == INT_MAX?"":s.substr(start,len); 60 } 61 62 };