0
点赞
收藏
分享

微信扫一扫

滑动窗口(双向队列)

上古神龙 2022-04-06 阅读 70

问题:

题目来自牛客网~

方法:

设数组元素为ai

解决这个题采用了双向队列,思路的话以求最大值为例,建立一个队列,然后遍历每个a[i],重复执行下面两个步骤

1.如果a[i] > 队尾的元素(说明队尾这个元素已经没有了成为最大值的可能),删除队尾元素,直到队尾元素 > a[i] 或者 队列为空

  如果a[i] < 队尾的元素(则当窗口滑动到这个队尾元素失效的时候,a[i] 有可能成为最大值),将a[i] 放入队列

如果此时 i >= k(窗口满元素) ,输出队头元素

2.从队头位置开始将所有不在窗口范围内的元素删除,因为滑动窗口只是同时判断 k 个元素的最大值

因为队列里直接放置 a[i] 的时候执行操作 2 会不方便,所以我们选择在队列里存放元素的下标 i

最小值同理

代码:

使用STL里 deque 的写法:

#include <iostream>
#include <deque>
#include <cstdio> 
using namespace std;
deque <int>q_max;
deque <int>q_min;
int n, k, a[1010];
int main(void)
{
    scanf("%d%d", &n,&k);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    //min
    for(int i = 1; i <= n; i++){
    	//去掉不在窗口内的元素
        while(i-q_min.front() >= k) q_min.pop_front();
        //a[i] < 队尾元素,删除队尾开始所有小于a[i]的元素
        while(!q_min.empty() && a[i] < a[q_min.back()]) q_min.pop_back();
        q_min.push_back(i);
        if(i >= k) cout <<a[q_min.front()] <<" ";
    }
    cout <<endl;
	//max
    for(int i = 1; i <= n; i++){
    	//去掉不在窗口内的元素
        while(i-q_max.front() >= k) q_max.pop_front();
        //a[i] > 队尾元素,删除队尾开始所有小于a[i]的元素
        while(!q_max.empty() && a[i] > a[q_max.back()]) q_max.pop_back();
        q_max.push_back(i);
        if(i >= k) cout <<a[q_max.front()] <<" ";
    }
    return 0;
}
举报

相关推荐

0 条评论