题目链接
https://leetcode-cn.com/problems/minimum-window-substring/
题目描述
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例: 输入: S = "ADOBECODEBANC", T = "ABC" 输出: "BANC" 说明: 如果 S 中不存这样的子串,则返回空字符串 ""。 如果 S 中存在这样的子串,我们保证它是唯一的答案。
解题思路
1.暴力枚举
双重for循环,从字符串S的每一个字符开始枚举,直到找到满足字符串T的子串,利用ans变量记录子串长度并进行迭代更新。
2.滑动窗口
标准的滑动窗口:
1.把[left,right]称为一个窗口;
2.先右移右指针扩大窗口,直到窗口中的数字满足字符串T数组要求;
3.满足要求时,停止增加right,转而增加left缩小窗口,直到不满足要求.
4.重复2,3步直到right走到字符串S的尽头。
滑动窗口的模板:
int left = 0, right = 0; //left right为双指针
while (right < s.size())
{
window.add(s[right]);
right++; //右移右指针扩大窗口
while (valid) //直到窗口中的字符串满足字符串T的要求;
{
window.remove(s[left]); //满足要求时,停止增加right,转而增加left缩小窗口,直到不满足要求
left++;
}
}
这题对于我来说,难点在与valid条件的判断,采用
if(window[s[r]] == mp[s[r]]) count++;
if(count == mp.size())
能够解决以下实例产生的问题:
S = "BBBBCEAW" T = "ABC"
S = "bbaa" T = "aba"
AC代码
1 class Solution { 2 public: 3 string minWindow(string s, string t) { 4 if(t.size() > s.size()) return ""; 5 if(s == t) return t; 6 map<char,int> mp; 7 for(int i = 0; i < t.size(); i++) mp[t[i]]++; 8 int l = 0; 9 int r = 0; 10 int count = 0; 11 int len = INT_MAX; 12 int start = -1; 13 map<char,int>window; 14 while(l <= r && r < s.size()) 15 { 16 if(mp.count(s[r]) == 1) 17 { 18 window[s[r]]++; 19 if(window[s[r]] == mp[s[r]]) count++; 20 } 21 22 if(count == mp.size()) //19行与22行代码就是对于valid条件的判断。 23 { 24 while(l < r) 25 { 26 if(window.count(s[l]) == 0) l++; 27 else if(window[s[l]] == mp[s[l]]) break; 28 else if(window[s[l]] > mp[s[l]]) 29 { 30 window[s[l]]--; 31 l++; 32 } 33 } 34 if(r-l+1 < len) 35 { 36 len = r-l+1; 37 start = l; 38 } 39 } 40 r++; 41 } 42 if(start != -1) return s.substr(start,len); 43 else return ""; 44 } 45 };