006_滑动窗口算法
是什么
左右指针维护一个滑动窗口
为什么
解决子串问题
有的滑动窗口大小固定, 但框架没必要修改, 这个框架最多判定2n次, 时间复杂度好点
怎么样
滑动窗口用[)区间更加方便
框架
s是要处理的串, n是一些子串的描述(如果说排列, 窗口大小肯定是固定的)
void slidingWindow(string s,string n) {
// 用合适的数据结构记录窗口中的数据
unordered_map<char, int> window,need;
for(char c : n)
{
need[c]++;
}
int left = 0, right = 0;
valid = 0;
//右侧增长
while (right < s.size()) {
char c = s[right];
right++;
// 进行窗口内数据的一系列更新
// ******** 如果这个c是我们需要的, 加入window, 然后和need对比, 看需不需要valid++
/*** debug 输出的位置 ***/
printf("window: [%d, %d)\n", left, right);
// 左侧是否需要收缩
while (left < right && window needs shrink) {
//一般在这里根据valid或者其他的条件输出
// ***********
char d = s[left];
left++;
// ******** 如果下一个循环就要被收缩掉的d是我们需要的, 和need对比, 看需不需要valid--, 移出window
}
}
}
增大窗口是每一次都会进行, 每一次窗口的增大都会影响窗口的缩小情况
3. 无重复字符的最长子串
76. 最小覆盖子串
438. 找到字符串中所有字母异位词
567. 字符串的排列
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> res;
//记录窗口数据
unordered_map<char,int> window,need;
for(char c : p)
{
need[c]++; //这个的初始默认是
}
int i=0;int j=0;
int valid=0;
//右侧
while(j<s.size())
{
char c=s[j];
j++;
//更新
if(need.count(c))
{
window[c]++;
if(window[c]==need[c]) valid++;
}
//左侧
while(j-i>=p.size()) //写了等于,底下的判断就不用加等于了, 一进来就判断一遍
{
if(valid==need.size())
{
res.emplace_back(i);
}
char d=s[i];
i++;
//更新
if(need.count(d)) //如果不判断,need[c]可能会改变need
{
if(window[d]==need[d]) valid--;
window[d]--;
}
}
}
return res;
}
};
这题我把一个d写成了c,debug了老半天.