零、前言:
众所周知,滑动窗口算法是算法学习中必须要掌握的算法之一,在蓝桥杯,acm,力扣等编程竞赛的题目中会出现,该算法还不算很难搞懂,是基础算法之一,所以我们要打好基础,下面让我们来学习滑动窗口。
一、滑动窗口的应用场景
滑动窗口算法 (Sliding Window)是一种常用的双指针算法,被广泛应用于字符串和数组等数据结构中的子串或子数组问题,例如字符串匹配、最长子串、最小覆盖子串等问题。 滑动窗口算法可以优化暴力枚举的时间复杂度,使得算法的执行效率更高。
二、滑动窗口的动态图
三、时间复杂度分析:
时间复杂度分析: 暴力解法的时间复杂度一般为O(N ^ 3):O(N ^ 2)枚举所有的子串,O(N)判断是否满足条件。
滑动窗口在两个方面都降低时间复杂度:首先并不枚举所有的子串,只枚举可能包含答案的那些。其次通过记录窗口内子串的一些信息,使得判断是否满足条件的时间复杂度下降。
四、经典例题
1、蓝桥杯经典真题——挑选子串
(帅哥们蓝色字体点进去可以看题目)
1.0、思路分析
这是一个很巧妙地思想将输入的数组所有数组元素大于等于m(a[i]>=m)变为1,反之为0,也就是我们在遍历数组该元素满足条件则子串计数器加1,让j先往后跑,若是字符串中满足条件元素的个数为k时就j让就停下,此时j往后的数组元素添加到该子字符串都满足所以将结果值ans+=j-i+1,i往后跑继续判断该子字符串是否满足,直到i,j都遍历完数组就结束。
1.1、代码分析
#include <iostream>
using namespace std;
int a[2001];
int slideWindow(int n,int k,int*a){
int i=0,j=-1,sum=0;
int ans=0;
while(j++<n){
sum+=a[j];
while(sum>=k){
ans+=n-j;
sum-=a[i];//i++以后将原来i在的位置的元素的值从计数器sum中减去
i++;
}
}
return ans;
}
int main()
{
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<n;i++){
cin>>a[i];
a[i]=(a[i]>=m?1:0);//将数组中所有大于m的值变成1,反之为0
}
int ans=slideWindow(n,k,a);
cout<<ans<<endl;
return 0;
}
2.0、思路分析
这题与第一题思路基本一样,就是用一个数组来记录每个元素(即s[i])的个数,表示方法为count[s[i]],其余的步骤都一样,换汤不换药。
2.1、代码分析
#include <iostream>
#include<string>
using namespace std;
int slideWindow(int n,int k,const string& s){
int i=0,j=-1;
int ans=0;
int count[256]={0};
while(j++<n-1){
count[s[j]]++;
while(count[s[j]]>k){
count[s[i]]--;//s[i]就是i++之前那个元素,这个元素要删除,所以要减1
i++;
}
int ret=j-i+1;
ans=max(ans,ret);
}
return ans;
}
int main()
{
string s;
int k;
cin>>s>>k;
int ans=slideWindow(s.size(),k,s);
cout<<ans<<endl;
return 0;
}
3.0、思路分析
这题与第一,二题思路也基本一样,就不过多解释了,相信你们理解前面两道题这道肯定手拿把掐。
3.1、代码分析
#include <iostream>
#include<cstring>
using namespace std;
int a[100001];
int slideWindow(int n,int*a){
int i=0,j=-1;
int cnt[1001]={0};
int need=0,sum=0,ret=n;//因为要找最短长度,所以把ret赋值最大长度n
for(int i=0;i<n;i++){
cnt[a[i]]++;
if(cnt[a[i]]==1)need++;//计算出所有不同元素的个数
}
memset(cnt,0,sizeof(cnt));//把计数数组全变回去,赋值为0
while(j++<n-1){
cnt[a[j]]++;
if(cnt[a[j]]==1)sum++;
while(sum==need){
ret=min(ret,j-i+1);
cnt[a[i]]--;
if(!cnt[a[i]])sum--;
i++;
}
}
return ret;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
int ans=slideWindow(n,a);
cout<<ans<<endl;
return 0;
}
希望各位帅哥可以点赞,关注支持一下,非常感谢!!!