滑动窗口算法总结

前言

我是会写Bug的子晗,生命不止,算法永不息!
昨天晚上,闲来无事去学校acm队训练机房呆了一会,太受刺激了,大一的把我摁在地上摩擦,属实很拉,学习了一个滑动窗口算法。唉,现在算法刚开课,之前自己也学过一段时间,但刷体很少。以后晚上得经常去跟着他们一起去训练了,这种行为我愿称之为“偷学"。(手动滑稽)

算法思想

我个人觉得滑动窗口算法思想与双指针相似,模拟一个窗口,创建的窗口逐渐滑动,根据题目给定的限制条件,来更新窗口边界,从而不断的更新题目所需值,当窗口滑动至边界时,这时也意味着,算法结束,即可获得所需值。一般情况下,右边界主动滑动,左边界被动滑动

俗话说的好,实践是检验真理的唯一标准!下面通过三道滑动窗口算法题来深层次理解滑动窗口算法的实际应用。

滑动窗口I

滑动窗口I

解题思路

通过设置两个指针,来作为窗口的边界,模拟窗口滑动,当窗口有右边界的字符已经存在于窗口内,左边界就需要更新。同时更新最大子串长度,当右指针移动至字符串末尾,窗口滑动完毕,所得值即为最大子串长度值。

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    while(getline(cin,s))
    {
        int i=0,j=0,curlen=0,maxlen=0;
        if(s.length()==0)
        {
            cout<<0<<endl;
            return 0;
        }
        for(;j<s.length();j++)
        {
            curlen++;
            for(int k=i;k<=j;k++)//扫描有无重复字符
            {
                if(s[k]==s[j+1])//存在重复字符
                {
                    if(curlen>maxlen) maxlen=curlen;//更新值
                    i=k+1;//跳过重复字符
                    curlen=j-i+1;//更新值
                    break;
                }
            }
        }
        maxlen=curlen>maxlen?curlen:maxlen;//更新值
        cout<<maxlen<<endl;
    }
    return 0;
}

滑动窗口II

在这里插入图片描述

解题思路

设置两个双指针,右指针滑动,当值出现大于等于m的情况时,进行值的更新,然后将左指针滑动至小于m,右指针继续滑动至上述情况进行处理,直到右指针滑动至窗口边界,算法结束。

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int Start=0,End=0,sum=0;
    int res=10000000;
    int n,m;
    cin>>n;
    int a[n];
    for(int i=0; i<n; i++)
        cin>>a[i];
    cin>>m;
    while(End<n)//右指针未到达边界
    {
        sum+=a[End];//右指针滑动
        if(sum>=m)//出现大于等于m的情况
        {
            res=min(res,End-Start+1);更新值
            while(sum>=m&&Start<=End)
            {
                res=min(res,End-Start+1);更新值
                sum-=a[Start];
                Start++;//左指针移动
            }
        }
        End++;//不满足情况,右指针继续移动
    }
    if(res==10000000)
        cout<<0<<endl;
    else
        cout<<res<<endl;
    return 0;
}

111111

在这里插入图片描述

解题思路

设置双指针,右指针滑动,当遇到1时,继续滑动,当遇到0时,判断此时窗口内的0的个数是否等于题目给定的m,如果等于,左指针移动,直到去除一个0为止,为新的0腾出位置。如果小于m,右指针继续移动。然后进行值的更新,直到右指针移动至窗口边界,算法结束。

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m,Max=0;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++)
        cin>>a[i];
    cin>>m;
    int left=0,right=0;
    for(;right<n;right++)
    {
        if(a[right]==0)
        {
            if(m==0)//到达限制条件
            {
                while(a[left]==1)
                    left++;
                left++;//去除一个0
            }
            else
                m--;
        }
        Max=max(right-left+1,Max);//更新值
    }
    cout<<Max<<endl;
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无所畏惧的man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值