02滑动窗口

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了02滑动窗口相关的知识,希望对你有一定的参考价值。

滑动窗口

笔者最早接触滑动窗口是滑动窗口协议,滑动窗口协议(Sliding Window Protocol),属于 TCP 协议的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生。 发送方和接收方分别有一个窗口大小 w1 和 w2。窗口大小可能会根据网络流量的变化而有所不同,但是在更简单的实现中它们是固定的。窗口大小必须大于零才能进行任何操作。

我们算法中的滑动窗口也是类似,只不过包括的情况更加广泛。实际上上面的滑动窗口在某一个时刻就是固定窗口大小的滑动窗口,随着网络流量等因素改变窗口大小也会随着改变。接下来我们讲下算法中的滑动窗口。

介绍

滑动窗口是一种解决问题的思路和方法,通常用来解决一些连续问题。 比如 LeetCode 的209. 长度最小的子数组 。更多滑动窗口题目见下方题目列表

常见套路

滑动窗口主要用来处理连续问题。比如题目求解“连续子串 xxxx”,“连续子数组 xxxx”,就应该可以想到滑动窗口。能不能解决另说,但是这种敏感性还是要有的。

从类型上说主要有:

  • 固定窗口大小
  • 窗口大小不固定,求解最大的满足条件的窗口
  • 窗口大小不固定,求解最小的满足条件的窗口(上面的 209 题就属于这种)

后面两种我们统称为可变窗口。当然不管是哪种类型基本的思路都是一样的,不一样的仅仅是代码细节。

固定窗口大小

对于固定窗口,我们只需要固定初始化左右指针 l l l r r r,分别表示的窗口的左右顶点,并且保证:

  1. l l l 初始化为 0
  2. 初始化 r r r,使得 r − l + 1 r - l + 1 rl+1 等于窗口大小
  3. 同时移动 l l l​ 和 r r r
  4. 判断窗口内的连续元素是否满足题目限定的条件
    • 4.1 如果满足,再判断是否需要更新最优解,如果需要则更新最优解
    • 4.2 如果不满足,则继续。

可变窗口大小

对于可变窗口,我们同样固定初始化左右指针 l l l r r r,分别表示的窗口的左右顶点。后面有所不同,我们需要保证:

  • 连续子数组可以表示为 [ l , r ] [l,r] [l,r]​ :从第 l l l​项到第 r r r​ 项。

    1. l l l r r r 都初始化为 0
    2. r r r 指针移动一步
  • 判断窗口 [ l , r ] [l,r] [l,r]内的连续元素是否满足题目限定的条件

    • 如果满足,再判断是否需要更新最优解,如果需要则更新最优解。并尝试通过移动 l l l 指针右移, 缩小窗口大小。循环执行 3.1
  • 如果窗口 [ l , r ] [l,r] [l,r] 不满足,此时应该扩张窗口, r r r右移,直到条件重新满足。

形象地来看的话,就是 r r r 指针不停向右移动, l l l 指针仅仅在窗口满足条件之后才会移动,起到窗口收缩的效果。

总结

  • 扩张窗口:为了找到一个可行解,找到了就不再扩张,因为扩张不再有意义。
  • 收缩窗口:在长度上优化该可行解,直到条件被破坏。
  • 继续寻找下一个可行解,然后再优化到不能优化……

模板代码

伪代码

初始化慢指针 = 0
初始化 ans

for 快指针 in 可迭代集合
   更新窗口内信息
   while 窗口内不符合题意
      扩展或者收缩窗口
      慢指针移动
   更新答案
返回 ans

代码

以下是 209 题目的代码,使用 Python 编写,大家意会即可。

class Solution:
    def minSubArrayLen(self, target, nums):
        if not nums:
            return 0
        
        n = len(nums)
        ans = n + 1
        l , r =0,0 
        total = 0
        while r<n:
            total +=nums[r]
            while total >=target: # 收缩窗口
                ans = min(ans,r-l+1)
                total -= nums[l]
                l +=1
            r+=1
        
        return 0 if ans==n+1 else ans

题目列表(有题解)

3. 无重复字符的最长子串

76. 最小覆盖子串

209. 长度最小的子数组

438. 找到字符串中所有字母异位词

以上是关于02滑动窗口的主要内容,如果未能解决你的问题,请参考以下文章

使用滑动片段显示数据而不是 ListView

在浏览量滑动上添加新片段

滑动时 ViewPager 更新片段

我的片段中有 webview,当滑动 webview 时, viewPager 也开始滑动

特定片段中的 Snackbar

如何让 videoView 在片段内播放?