侧边栏壁纸
博主头像
Hope博主等级

努力赚钱的工科研究生

  • 累计撰写 362 篇文章
  • 累计创建 129 个标签
  • 累计收到 5 条评论
标签搜索

滑动窗口

Hope
2022-04-03 / 0 评论 / 0 点赞 / 473 阅读 / 861 字
温馨提示:
本文最后更新于 2022-04-03,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

使用数据结构: 单调队列(实际是单调双端队列,队头队尾可删)

每次维护一个窗口,为了满足某种性质,需要对队列进行维护。

如何判断是否有单调性?
先看暴力是怎么做的,然后正常维护过程,然后把不需要的元素删掉,之后判断,剩余的元素是否具有单调性。

看下面的例子,题目的要求是找窗口中的最小值。

image.png

对于这样的一个数组,窗口大小为3,随着i的不断增加,寻找窗口内的最小值,我们可以发现只要 -1 存在一天,前面的 1 和 3就不会被输出。

同样:
image.png

只要-1存在,比它大的就不会被用到。
...

所以这个队列里面的元素就是单调减小的。

例题:
154. 滑动窗口

参考代码:

#include<iostream>
using namespace std;

const int N = 1e6+10;
int a[N],q[N];
int hh = 0, tt = -1;
int n,k;

int main(){
    cin>>n>>k;
    for(int i = 0; i < n; i++) cin>>a[i];
    
    for(int i = 0; i < n; i++){
        //如果队头滑出了队列 更新队头
        if(hh <= tt && q[hh] < i - k + 1) hh++;
        //如果队尾的元素大于等于当前元素,则一直不会被用到
        while(hh <= tt && a[q[tt]] >= a[i]) tt--;
        q[++tt] = i;
        
        if(i >= k - 1) cout<<a[q[hh]]<<" ";
    }
    puts("");
    
    hh = 0,tt = - 1;
    
    for(int i = 0; i < n; i++){
        if(hh <= tt && q[hh] < i - k + 1) hh++;
        while(hh <= tt && a[q[tt]] <= a[i]) tt--;
        q[++tt] = i;
        if(i >= k - 1) cout<<a[q[hh]]<<" ";
    }
    
    
    return 0;
}
0

评论区