微軟面試題: LeetCode 76. 最小覆蓋子串 出現次數:2

題目描述: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 };
相關文章
相關標籤/搜索