写在前面
什么是数组当中的滑动窗口,故名思意,即在一个连续数组中通过两个指针(数组下标索引)分别作为窗口的起始位置和结束位置,形成一个起始位置和结束位置可以改变的窗口,这个窗口内的元素其实也就是数组中连续的子序列。一般题目中要求寻找某种符合要求的子序列时,可以考虑使用滑动窗口的思想。
注意:滑动窗口也是在一个数组中使用两个指针进行标识,读者可以在看完本篇文章内容以后同我前面介绍的双指针技巧加以区分,这边先附上链接:
leetcode刷题技巧(一):双指针
接下来通过一个例子来具体介绍一下滑动窗口的用法:leetcode209题:长度最小的子数组。
一,leetcode209题:长度最小的子数组
1.1 题目
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
1.2 思路
很明显,题目要求从整体数组中寻找一个符合要求的子数组,因此我们尝试使用滑动窗口,在使用滑动窗口之前,我们先仔细分析一下他的要求,以确定待会的滑动窗口应该怎样动态调节。通过分析,题目要求如下:
1,要求窗口内的元素之和>target。
2,要求窗口内的元素个数尽可能少。
因此,我们可以设置low与high指针分别表示窗口的起始索引和结束索引,刚开始时,两者都指向0,让high指针向右移动,直到low至high窗口内的元素之和>target,此时再移动low指针,即缩小窗口的大小,看窗口内元素之和还会不会依然>target,如果依然满足,则说明我们的窗口成功缩小了;如果不满足>target,则说明以目前high结尾的窗口已经找到了使其窗口元素之和>target,又元素个数最小的情况。那就继续让high向右移动,再次遇到窗口内元素之和>target时,再移动low指针尝试缩小窗口。最后直到high指针不可再移动。
1.3 代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int ans=INT32_MAX;
int low=0;
int high=0;
int now_num=nums[0];
while(high<=nums.size())
{
if(now_num<target){//右指针向右移动一格
high++;
if(high<nums.size())
now_num+=nums[high];//新的窗口值
}
else{//说明现在的窗口值>=target了,已经满足条件
ans=min_judge(ans,high-low+1);
if(ans==1) return ans;
else{
low++;//让窗口向右边缩小长度,在下一次循环中继续判断其窗口值是否满足条件
now_num=now_num-nums[low-1];//更新窗口值
}
}
}
if(ans!=INT32_MAX) return ans;
else return 0;
}
int min_judge(int a,int b)
{
if(a<b)return a;
else return b;
}
};
1.4 总结
这道题目仅仅是初步见识了一下滑动窗口,因为本道题目的要求,所以滑动窗口才会有对应的滑动规则,high指针与low指针起什么作用,high指针与low指针如何移动,这些都是为题目的具体要求服务的。读者遇到应该使用滑动窗口之类的题目应该具体问题具体分析,而这道题目的建设性在于,给读者一个直观的滑动窗口类型题目的表现,让读者在脑海中形成一个用滑动窗口解决问题的模型,有了这个模型将帮助读者在遇到类似的可以用滑动窗口解决的问题时提供一个可行的方向。接下来读者还可以尝试做一做leetcode上面的第3题:无复字符的最长子串;
PS:抱歉各位读者,本来打算最近认真总结写一写算法专题的,但发现认真写下来还是颇费时间的,我现在正在考研,等考研初试结束以后再更新吧!谢谢大家的支持。