微软面试题: 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 };
相关文章
相关标签/搜索