滑动窗口问题:
滑动窗口这类问题一般需要用到双指针来进行求解,一般都是基于字符串和数组的。
-
给两个字符串,一长一短,问其中短的是否在长的中满足一 定的条件存在,例如:求短的字符串在长的字符串中出现的所有位置
-
给一个字符串或者数组,问这个字符串的子串或者子数组是否满足一 定的条件。例如:
-
含有少于k个不同字符的最长子串
-
所有字符都只出现一次的最长子串
除此之外。还有一些其他的问法。但是不变的是。这类题目脱离不开主串(主数组)和子串(子数组)的关系,要求的时间复杂度往往是0(n),空间复杂度往往是常数级的。
题目描述:
给定一个含有n个整数的数组和一个正整数s,找出数组中的子串满足其和>=s的最小连续子数组的长度。
例如:
给的数组为2,3,1,2,4,3,s为7,因此输出的值就应该为2,即4+3
如何来求解这道题呢?
第一种方法就是暴力解法,循环遍历每个数,然后和后边的数相加,判断是否大于s,在求最小值,时间复杂度为O(N^2),对于一般题目显然会超时,因此这里就需要使用滑动窗口来解决
滑动窗口主要用来处理连续问题。比如题目求解连续子串xxx,连续子数组xxx".就应该可以想到滑动窗口。
从类型上说主要有:
-
固定窗口大小
-
窗口大小不固定,求解最大的满足条件的窗口
-
窗口大小不固定,求解最小的满足条件的窗口
窗口大小不固定:
对于可变窗口,我们同样固定初始化左右指针 l 和r,分别表示的窗口的左右顶点。我们需要保证:
-
l和r都初始化为1
-
r指针移动1步
-
判断窗口内的连续元素是否满足题目限定的条件
- 如果满足,再判断是否需要更新最优解,如果需要则更新最优解。井尝试通过移动 I 指针缩小窗口大小。
- 循环执行上一步, 如果不满足,则继续将r指针加一。
时间复杂度: 0(n)
下边是代码:
#include <iostream>
using namespace std;
#define inf 0x3f3f3f3f
int n,s,ans;
int a[1005];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
cin>>s;//找出和>=s的最小连续子数组的长度
int l=1;//左指针
int r=1;//右指针
int tot=0;//记录子数组的和
ans=inf;
for(r=1;r<=n;r++)
{
tot+=a[r];
while(tot>=s)
{
ans=min(ans,r-l+1);//r-l+1为子数组长度
tot-=a[l];
l+=1;
}
}
cout<<ans<<endl;
return 0;
}