Algorithm-SlidingWindow

date
Oct 24, 2023
slug
algorithm-slidingWindow
status
Published
tags
algorithm
type
Post
https://twitter.com/tangdahe
summary
sliding window

滑动窗口

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果
在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
那么滑动窗口如何用一个for循环来完成这个操作呢。
首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置。
如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?
此时难免再次陷入 暴力解法的怪圈。
所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。
那么问题来了, 滑动窗口的起始位置如何移动呢?
 

209 长度最小的子数组

这里还是以题目中的示例来举例,s=7, 数组是 2,3,1,2,4,3,7来看一下查找的过程:
notion image
notion image
其实从图示中可以发现滑动窗口也可以理解为双指针法的一种!只不过这种解法更像是一个窗口的移动,所以叫做滑动窗口更适合一些。
在本题中实现滑动窗口,主要确定如下三点:
  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
解题的关键在于 窗口的起始位置如何移动,如图所示:
notion image
可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
 
 

904 水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
  • 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
该题同样采用滑动窗口思路解答,需要找出对应的条件:
  • 窗口内是什么?
    • 这里应该为最多两种类型的水果序列(本题只有两个篮子)
  • 如何移动窗口的起始位置?
    • 这里为窗口中目前所包含的类型,大于 2,就需要前移
  • 如何移动窗口的结束位置?
    • 如果当前窗口中所含水果种类小于等于2,就可以一直前移,其实也就是外部 for 循环 idx
因为需要记录水果类型,这里需要使用 map 结构,记录每种类型的水果在当前窗口内有多少的数量
 
 
 

76 最小覆盖字串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。
思路:滑动窗口
  • 窗口内是什么?
    • 包含目标字符串 T 中所有的字符类型和对应数量,可以多
  • 如何移动窗口的起始位置?
    • 大于 T 的有效统计长度,就可以前移,不符合就要停止移动
  • 如何移动窗口的结束位置?
    • 外部 for 循环 idx

© Craig Hart 2021 - 2024