|
| 1 | +# 滑动窗口(Sliding Window) |
| 2 | + |
| 3 | +笔者最早接触滑动窗口是`滑动窗口协议`,滑动窗口协议(Sliding Window Protocol),属于 TCP 协议的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生。 发送方和接收方分别有一个窗口大小 w1 和 w2。窗口大小可能会根据网络流量的变化而有所不同,但是在更简单的实现中它们是固定的。窗口大小必须大于零才能进行任何操作。 |
| 4 | + |
| 5 | +我们算法中的滑动窗口也是类似,只不过包括的情况更加广泛。实际上上面的滑动窗口在某一个时刻就是固定窗口大小的滑动窗口,随着网络流量等因素改变窗口大小也会随着改变。接下来我们讲下算法中的滑动窗口。 |
| 6 | + |
| 7 | +## 介绍 |
| 8 | + |
| 9 | +滑动窗口是一种解决问题的思路和方法,通常用来解决一些连续问题。 比如 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/)。更多滑动窗口题目见下方`题目列表`。 |
| 10 | + |
| 11 | +## 常见套路 |
| 12 | + |
| 13 | +滑动窗口主要用来处理连续问题。比如题目求解“连续子串 xxxx”,“连续子数组 xxxx”,就应该可以想到滑动窗口。能不能解决另说,但是这种敏感性还是要有的。 |
| 14 | + |
| 15 | +从类型上说主要有: |
| 16 | + |
| 17 | +- 固定窗口大小 |
| 18 | +- 窗口大小不固定,求解最大的满足条件的窗口 |
| 19 | +- 窗口大小不固定,求解最小的满足条件的窗口(上面的 209 题就属于这种) |
| 20 | + |
| 21 | +后面两种我们统称为`可变窗口`。当然不管是哪种类型基本的思路都是一样的,不一样的仅仅是代码细节。 |
| 22 | + |
| 23 | +### 固定窗口大小 |
| 24 | + |
| 25 | +对于固定窗口,我们只需要固定初始化左右指针 l 和 r,分别表示的窗口的左右顶点,并且保证: |
| 26 | + |
| 27 | +1. l 初始化为 0 |
| 28 | +2. 初始化 r,使得 r - l + 1 等于窗口大小 |
| 29 | +3. 同时移动 l 和 r |
| 30 | +4. 判断窗口内的连续元素是否满足题目限定的条件 |
| 31 | + - 4.1 如果满足,再判断是否需要更新最优解,如果需要则更新最优解 |
| 32 | + - 4.2 如果不满足,则继续。 |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +### 可变窗口大小 |
| 37 | + |
| 38 | +对于可变窗口,我们同样固定初始化左右指针 l 和 r,分别表示的窗口的左右顶点。后面有所不同,我们需要保证: |
| 39 | + |
| 40 | +1. l 和 r 都初始化为 0 |
| 41 | +2. r 指针移动一步 |
| 42 | +4. 判断窗口内的连续元素是否满足题目限定的条件 |
| 43 | + - 4.1 如果满足,再判断是否需要更新最优解,如果需要则更新最优解。并尝试通过移动 l 指针缩小窗口大小。循环执行 4.1 |
| 44 | + - 4.2 如果不满足,则继续。 |
| 45 | + |
| 46 | +形象地来看的话,就是 r 指针不停向右移动,l 指针仅仅在窗口满足条件之后才会移动,起到窗口收缩的效果。 |
| 47 | + |
| 48 | + |
| 49 | + |
| 50 | +## 模板代码 |
| 51 | + |
| 52 | +以下是 209 题目的代码,使用 Python 编写,大家意会即可。 |
| 53 | + |
| 54 | +```python |
| 55 | +class Solution: |
| 56 | + def minSubArrayLen(self, s: int, nums: List[int]) -> int: |
| 57 | + l = total = 0 |
| 58 | + ans = len(nums) + 1 |
| 59 | + for r in range(len(nums)): |
| 60 | + total += nums[r] |
| 61 | + while total >= s: |
| 62 | + ans = min(ans, r - l + 1) |
| 63 | + total -= nums[l] |
| 64 | + l += 1 |
| 65 | + return 0 if ans == len(nums) + 1 else ans |
| 66 | +``` |
| 67 | + |
| 68 | +## 题目列表 |
| 69 | + |
| 70 | +以下题目有的信息比较直接,有的题目信息比较隐蔽,需要自己发掘 |
| 71 | + |
| 72 | +- [【Python,JavaScript】滑动窗口(3. 无重复字符的最长子串)](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/pythonjavascript-hua-dong-chuang-kou-3-wu-zhong-fu/) |
| 73 | +- [76. 最小覆盖子串](https://leetcode-cn.com/problems/minimum-window-substring/solution/python-hua-dong-chuang-kou-76-zui-xiao-fu-gai-zi-c/) |
| 74 | +- [209. 长度最小的子数组](https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/209-chang-du-zui-xiao-de-zi-shu-zu-hua-dong-chua-2/) |
| 75 | +- [【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/) |
| 76 | +- [【904. 水果成篮】(Python3)](https://leetcode-cn.com/problems/fruit-into-baskets/solution/904-shui-guo-cheng-lan-python3-by-fe-lucifer/) |
| 77 | +- [【930. 和相同的二元子数组】(Java,Python)](https://leetcode-cn.com/problems/binary-subarrays-with-sum/solution/930-he-xiang-tong-de-er-yuan-zi-shu-zu-javapython-/) |
| 78 | +- [【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/) |
| 79 | +- [【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/) |
| 80 | +- [【1234. 替换子串得到平衡字符串】[Java/C++/Python] Sliding Window](https://leetcode.com/problems/replace-the-substring-for-balanced-string/discuss/408978/javacpython-sliding-window/367697) |
| 81 | +- [【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/) |
| 82 | + |
| 83 | +## 扩展阅读 |
| 84 | + |
| 85 | +- [LeetCode Sliding Window Series Discussion](https://leetcode.com/problems/binary-subarrays-with-sum/discuss/186683/) |
0 commit comments