滑动窗口题目模板
参考:https://labuladong.gitbook.io/algo/mu-lu-ye-1/mu-lu-ye-3/hua-dong-chuang-kou-ji-qiao-jin-jie
/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
unordered_map<char, int> need, window;
for (char c : t) need[c]++;
int left = 0, right = 0;
int valid = 0;
while (right < s.size()) {
// c 是将移入窗口的字符
char c = s[right];
// 右移窗口
right++;
// 进行窗口内数据的一系列更新
...
/*** debug 输出的位置 ***/
printf("window: [%d, %d)\n", left, right);
/********************/
// 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 左移窗口
left++;
// 进行窗口内数据的一系列更新
...
}
}
}
题目出处:leet567
题目:
给你两个字符串 s1
和 s2
,写一个函数来判断 s2
是否包含 s1
的排列。
换句话说,s1
的排列之一是 s2
的 子串 。
思路:构建2个map一个储存s1子串need,一个当window。右窗口滑动更新:如果右边窗口的字符在need中出现,这个need++,当某个字符数量和s1串里的数量一样时判断是否包含所有S1字符的变量valid++。左窗口收缩条件:窗口大小大于等于子串s1大小则收缩。当valid=s1.size()时表示这时找到子串位置返回true,否则收缩左窗口。
class Solution {
public:
// 判断 s 中是否存在 t 的排列
bool checkInclusion(string t, string s)
{
unordered_map<char,int>need,window;
for(int i=0;i<t.size();i++)
need[t[i]]++;
int left=0,right=0;
int valid=0;
while(right<s.size())
{
char c=s[right];
right++;
if(need.count(c))
{
window[c]++;
if(window[c]==need[c])
valid++;
}
while(right-left>=t.size())
{
if(valid==need.size())
return true;
char d=s[left];
left++;
if(need.count(d))
{
if(window[d]==need[d])
valid--;
window[d]--;
}
}
}
return false;
}
};
出处:leet76
题目:给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
思路:同567,左窗口收缩条件改变成当valid符合need.size()时就进行最小子串位置更新,判断当前更新子串长度是否比现在的小
class Solution {
public:
string minWindow(string s, string t)
{
int left=0,right=0;
int valid=0,len=INT_MAX;
int start=0;
unordered_map<char,int>window,need;
for(int i=0;i<t.size();i++)
{
need[t[i]]++;
}
while(right<s.size())
{
char c=s[right];
right++;
if(need.count(c))
{
window[c]++;
if(window[c]==need[c])
{
valid++;
}
}
while(valid==need.size())
{
if(right-left<len)
{
start=left;
len=right-left;
}
char d=s[left];
left++;
if(need.count(d))
{
if(window[d]==need[d])
{
valid--;
}
window[d]--;
}
}
}
if(len==INT_MAX)
return "";
else return s.substr(start,len);
}
};
出处:leet3
题目:
思路:左窗口移动条件:当窗口最右边的字符在map中大于1时左窗口左移,直到map中字符数量等于1。此时记录left和right下标,right-left作为当前更新的最长子串长度与之前最长子串取最大值。
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> window;
int left = 0, right = 0;
int res = 0; // 记录结果
while (right < s.size()) {
char c = s[right];
right++;
// 进行窗口内数据的一系列更新
window[c]++;
// 判断左侧窗口是否要收缩
while (window[c] > 1) {
char d = s[left];
left++;
// 进行窗口内数据的一系列更新
window[d]--;
}
// 在这里更新答案
res = max(res, right - left);
}
return res;
}