子数组之滑动窗口篇

904. 水果成篮

795. 区间子数组个数

992. K 个不同整数的子数组

 

前文总结过子数组相关问题可以简单的分为三类,使用的方法可分为三种,即:「前缀和」「滑动窗口」「动态规划」。详情可见 秒杀子数组类题目

而今天这一篇是「滑动窗口解决子数组问题」的专题!!(主要是遇到了一种用滑动窗口的高级小技巧,忍不住想分享出来)

先来回顾一下「滑动窗口解决子数组问题」的两个特点:

那么废话不多说,直接今天的题目!!!

水果成篮

题目详情可见 水果成篮

首先我们分析一下题目是否符合「滑动窗口解决子数组问题」中总结的两个特点

「只有两个篮子,并且每个篮子只能装单一类型的水果,要求摘到的水果数量最多」说人话就是「子数组中最多只能包含两个不同的元素,求子数组的最大长度」

是不是「研究对象」为单个的元素,而不是子数组的元素之和!!

是不是「约束条件」为一个范围,即:不同元素的数量>= k

说白了,这就是一个典型的「滑动窗口解决子数组问题」的模版题,控制滑动窗口移动的因素是窗口内不同元素的个数

下面给出完整代码:

区间子数组个数

题目详情可见 区间子数组个数

按照惯例,首先我们分析一下题目是否符合「滑动窗口解决子数组问题」中总结的两个特点

「最大元素在范围[left, right]中的所有子数组个数」

是不是「研究对象」为单个的元素,而不是子数组的元素之和!!

是不是「约束条件」为一个范围,即:left <= max <= right

如果我们想把窗口内最大元素控制在left <= max <= right范围中,其实是不可行的,会出现答案的不完整,有兴趣的可以去模拟一下整个过程

这个时候我们需要曲线救国:如果我们把最大元素<= right的子数组数量算出来,然后再把最大元素<= left - 1的子数组数量算出来,两者相减不就是最终答案了嘛

其实我们可以把「约束条件」中的第二个特点再限定一波:必须是[-∞, k]或者[k, +∞]。如果遇到[left, right]这种范围可以转换一下,来一波曲线救国

下面给出完整代码:(这个题目相对而言比较简单,所以可能没有很明显的滑动窗口模版的那些套路,但底层的原理就是滑动窗口)

K 个不同整数的子数组

题目详情可见 K 个不同整数的子数组

上个题目「滑动窗口」不是很明显,这个题目就超级明显,可以说是滑动窗口的亲儿子了

按照惯例,首先我们分析一下题目是否符合「滑动窗口解决子数组问题」中总结的两个特点

「不同整数的个数恰好为k的所有子数组个数」

是不是「研究对象」为单个的元素,而不是子数组的元素之和!!

但是这个「约束条件」确给出了给出了具体的限定,即:不同整数的个数恰好为k

下面给出一种错误版本的代码:

对于样例[1,2,1,2,3],会遗漏答案[2,1]

其实可以很明显的看出来,对于一个具体区间的限定,如本题可以看作[k, k],而上一题是[left, right],在收缩窗口的时候会出现一些问题,所以我们需要像上一题一样曲线救国

如果我们把不同整数的个数<= k - 1的子数组数量算出来,然后再把不同整数的个数<= k的子数组数量算出来,两者相减不就是最终答案了嘛

所以我们需要把代码稍微修改一下即可: