154. 滑动窗口

Posted 幽殇默

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了154. 滑动窗口相关的知识,希望对你有一定的参考价值。

在这里插入图片描述
https://www.acwing.com/problem/content/156/

总的代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e6+10;
int q[N],a[N],hh,tt=-1;
int main(void)
{
    int n,k; cin>>n>>k;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int i=0;i<n;i++)
    {
        if(i-k+1>q[hh]) hh++;
        while(hh<=tt&&a[i]<a[q[tt]]) tt--;
        q[++tt]=i;
        if(i+1>=k) cout<<a[q[hh]]<<" ";
    }
    cout<<endl;
    
    hh=0,tt=-1;
    for(int i=0;i<n;i++)
    {
        if(i-k+1>q[hh]) hh++;
        while(hh<=tt&&a[i]>a[q[tt]]) tt--;
        q[++tt]=i;
        if(i+1>=k) cout<<a[q[hh]]<<" ";
    }
    cout<<endl;
    return 0;
}

首先你要知道 q [ N ] 这个数组里存放的是下标
因为只有存下标,我们才知道当前的滑动窗口的对头 有没有出界,要不要对头弹出。

if(i-k+1>q[hh]) hh++; //保证了滑动窗口不会出界

其次当一个数进队的时候,如果它比队尾元素小,那么队尾弹出,直到一个数比其小或者队为空了,它进队。
因为我们上面已经保证在同一个的滑动窗口了,那么前面比其大的数都不可能作为一个最小数的候选人。

那么为何当一个数比其末尾数大的数,我们直接入队的呢?
是这样的,这说明这个数可能不是当前状态下最小的数,但是可能是当滑动窗口移动后的一个最小数。
因为滑动窗口是移动的,当窗口溢出的时候对头就要出去了,故大的数可能是候选人。

 while(hh<=tt&&a[i]<a[q[tt]]) tt--;

最后,队头元素保存了当前位置滑动窗口的最小数的下标,直接输出队头元素所对应的值

if(i+1>=k) cout<<a[q[hh]]<<" ";

以上是关于154. 滑动窗口的主要内容,如果未能解决你的问题,请参考以下文章

Acwing 154 滑动窗口(单调队列)经典模板

AcWing 154. 滑动窗口

154. 滑动窗口单调队列

AcWing 154. 滑动窗口

滑动窗口(单调队列) C++版 Python版本

Acwing -- 单调队列优化的DP问题