# 滑动窗口(思路 + 模板) # 滑动窗口(Sliding Window) 笔者最早接触滑动窗口是`滑动窗口协议`,滑动窗口协议(Sliding Window Protocol),属于 TCP 协议的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生。 发送方和接收方分别有一个窗口大小 w1 和 w2。窗口大小可能会根据网络流量的变化而有所不同,但是在更简单的实现中它们是固定的。窗口大小必须大于零才能进行任何操作。 我们算法中的滑动窗口也是类似,只不过包括的情况更加广泛。实际上上面的滑动窗口在某一个时刻就是固定窗口大小的滑动窗口,随着网络流量等因素改变窗口大小也会随着改变。接下来我们讲下算法中的滑动窗口。 ## 介绍 滑动窗口是一种解决问题的思路和方法,通常用来解决一些连续问题。 比如 LeetCode 的 [209. 长度最小的子数组](https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/209-chang-du-zui-xiao-de-zi-shu-zu-hua-dong-chua-2/)。更多滑动窗口题目见下方`题目列表`。 ## 常见套路 滑动窗口主要用来处理连续问题。比如题目求解“连续子串 xxxx”,“连续子数组 xxxx”,就应该可以想到滑动窗口。能不能解决另说,但是这种敏感性还是要有的。 从类型上说主要有: - 固定窗口大小 - 窗口大小不固定,求解最大的满足条件的窗口 - 窗口大小不固定,求解最小的满足条件的窗口(上面的 209 题就属于这种) 后面两种我们统称为`可变窗口`。当然不管是哪种类型基本的思路都是一样的,不一样的仅仅是代码细节。 ### 固定窗口大小 对于固定窗口,我们只需要固定初始化左右指针 l 和 r,分别表示的窗口的左右顶点,并且保证: 1. l 初始化为 0 2. 初始化 r,使得 r - l + 1 等于窗口大小 3. 同时移动 l 和 r 4. 判断窗口内的连续元素是否满足题目限定的条件 - 4.1 如果满足,再判断是否需要更新最优解,如果需要则更新最优解 - 4.2 如果不满足,则继续。 ![](https://img.kancloud.cn/71/1d/711d4d8b2610643559cf5feb7c073fce_323x473.jpg) ### 可变窗口大小 对于可变窗口,我们同样固定初始化左右指针 l 和 r,分别表示的窗口的左右顶点。后面有所不同,我们需要保证: 1. l 和 r 都初始化为 0 2. r 指针移动一步 3. 判断窗口内的连续元素是否满足题目限定的条件 - 3.1 如果满足,再判断是否需要更新最优解,如果需要则更新最优解。并尝试通过移动 l 指针缩小窗口大小。循环执行 3.1 - 3.2 如果不满足,则继续。 形象地来看的话,就是 r 指针不停向右移动,l 指针仅仅在窗口满足条件之后才会移动,起到窗口收缩的效果。 ![](https://img.kancloud.cn/0f/4b/0f4b9bf17cc417c0cb717c7ee3c95f11_477x473.jpg) ## 模板代码 ### 伪代码 ``` <pre class="calibre18">``` 初始化慢指针 = 0 初始化 ans for 快指针 in 可迭代集合 更新窗口内信息 while 窗口内不符合题意 扩展或者收缩窗口 慢指针移动 返回 ans ``` ``` ### 代码 以下是 209 题目的代码,使用 Python 编写,大家意会即可。 ``` <pre class="calibre18">``` <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">minSubArrayLen</span><span class="hljs-params">(self, s: int, nums: List[int])</span> -> int:</span> l = total = <span class="hljs-params">0</span> ans = len(nums) + <span class="hljs-params">1</span> <span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> range(len(nums)): total += nums[r] <span class="hljs-keyword">while</span> total >= s: ans = min(ans, r - l + <span class="hljs-params">1</span>) total -= nums[l] l += <span class="hljs-params">1</span> <span class="hljs-keyword">return</span> <span class="hljs-params">0</span> <span class="hljs-keyword">if</span> ans == len(nums) + <span class="hljs-params">1</span> <span class="hljs-keyword">else</span> ans ``` ``` ## 题目列表(有题解) 以下题目有的信息比较直接,有的题目信息比较隐蔽,需要自己发掘 - [【Python,JavaScript】滑动窗口(3. 无重复字符的最长子串)](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/pythonjavascript-hua-dong-chuang-kou-3-wu-zhong-fu/) - [76. 最小覆盖子串](https://leetcode-cn.com/problems/minimum-window-substring/solution/python-hua-dong-chuang-kou-76-zui-xiao-fu-gai-zi-c/) - [209. 长度最小的子数组](https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/209-chang-du-zui-xiao-de-zi-shu-zu-hua-dong-chua-2/) - [【Python】滑动窗口(438. 找到字符串中所有字母异位词)](https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/solution/python-hua-dong-chuang-kou-438-zhao-dao-zi-fu-chua/) - [【904. 水果成篮】(Python3)](https://leetcode-cn.com/problems/fruit-into-baskets/solution/904-shui-guo-cheng-lan-python3-by-fe-lucifer/) - [【930. 和相同的二元子数组】(Java,Python)](https://leetcode-cn.com/problems/binary-subarrays-with-sum/solution/930-he-xiang-tong-de-er-yuan-zi-shu-zu-javapython-/) - [【992. K 个不同整数的子数组】滑动窗口(Python)](https://leetcode-cn.com/problems/subarrays-with-k-different-integers/solution/992-k-ge-bu-tong-zheng-shu-de-zi-shu-zu-hua-dong-c/) - [【1004. 最大连续 1 的个数 III】滑动窗口(Python3)](https://leetcode-cn.com/problems/max-consecutive-ones-iii/solution/1004-zui-da-lian-xu-1de-ge-shu-iii-hua-dong-chuang/) - [【1234. 替换子串得到平衡字符串】\[Java/C++/Python\] Sliding Window](https://leetcode.com/problems/replace-the-substring-for-balanced-string/discuss/408978/javacpython-sliding-window/367697) - [【1248. 统计「优美子数组」】滑动窗口(Python)](https://leetcode-cn.com/problems/count-number-of-nice-subarrays/solution/1248-tong-ji-you-mei-zi-shu-zu-hua-dong-chuang-kou/) ## 扩展阅读 - [LeetCode Sliding Window Series Discussion](https://leetcode.com/problems/binary-subarrays-with-sum/discuss/186683/)