一、滑动窗口概念
滑动窗口本质属于双指针(左右指针 left、right)。
窗口:left , right 一段连续的子数组、子串。
1、right:不断向右扩张窗口(加入新元素)
2、left:当窗口不满足条件时,向右收缩窗口(去掉左边元素)
3、两个指针只会往前走,不会回退,时间复杂度:O(n),远优于暴力二重循环O(n的二次方)
适用场景:求连续子数组 / 子串的最值、长度、和、无重复等问题
二、滑动窗口 2 大类型
1、不定长窗口
窗口大小不固定,left 根据条件动态移动
2、定长窗口
窗口长度固定,right、left 同步移动
三、通用解题步骤
1、初始化左指针 left = 0
2、for 循环遍历右指针 right,逐个把元素放进窗口
3、更新窗口内当前状态(和、字符频次、重复标记等)
4、while 循环判断窗口是否不合法:如果不合法,移动左指针缩小窗口,更新状态,left++
5、合法时更新答案结果
6、right 继续右移
四、滑动窗口万能伪代码模板
题目:无重复字符的最长子串
给定一个字符串s,找出其中不含重复字符的最长子串的长度。
例如s="abcabcabc", 答案:3(abc)
完整代码:
思路:
1、定义窗口区间 left , right,代表当前正在考察的子串;
2、right 指针一个个往右走,把新字符放进窗口;
3、每加入一个新字符,就记录这个字符出现过多少次;
4、一旦窗口里面出现重复字符:窗口就非法了;开启 while 循环,不断把窗口左边的字符移除,left 向右移动;一直缩窗口,直到窗口内没有重复字符为止;
5、窗口变成合法(无重复)之后,计算当前窗口的长度,更新最长长度;
6、right 走到字符串末尾,结束,返回最长长度。
口诀:右扩窗口,遇重缩左,合法更新答案

1、标准输入输出头文件,用来使用printf打印结果。
2、字符串头文件,提供strlen()函数,计算字符串长度。

自定义函数,参数char* s就是传入的字符串;返回值int代表最长子串长度。

1、freq全称frequency,频次;
2、所有英文字母,符号ASCII编号都在0-127;
3、freq'a'就代表字符a在当前窗口出现多少次;
4、={0}:数组全部元素初始化位0,一开始窗口里面没有任何字符。

1、窗边左边界,起始位置从下标0开始。
2、记录答案,初始最长长度位0,后面不断更新。
3算出字符串一共有多少个字符,用于for循环结束条件。

right就是敞口的右边界,循环每执行一次,右边界向右挪一格,扩大窗口。

1、sright取出字符串中下标为right的字符,存到变量rChar。
2、刚取到的这个字符,放进窗口。窗口中该字符出现次数 + 1。

freqrChar>1:刚刚放进来的这个字符,窗口现在出现了两次--->窗口有重复
注意:这里必须用while,不能用if
if只会收缩窗口一次;while会一直收缩,直到重复消失。

1、拿到窗口左边的字符,准备把它移出窗口。
2、左边的字符离开窗口,它的出现次数-1。
左边界向右移动一格,窗口从左边缩短。然后回到while条件,再次检查还有没有重复字符;只要还重复,就继续缩窗口。
计算当前窗口的字符数量(子串长度)
现在窗口合法无重复;对比当前窗口长度和历史最长长度,如果更长,就更新最长长度。
循环结束,right遍历完整个字符串;返回最终最长长度。