滑动窗口(deque)

题意:用一个窗口来框住几个连续的元素,问每次框住元素的最大值和最小值

这里可以用deque来完美解决这个问题,deque是一种特殊的queue,他在queue的基础上增加了从开头插入,从队尾删除等操作,我们用两个deque分别来维护最大值和最小值,我这里讲一下最大值的做法,最小值一样。

每次向队列里插入元素的时候,都要和队尾元素比较,如果队尾元素小于插入元素,则将队尾元素出队,插入元素和新的队尾继续比较,直至队列已空或者是队尾元素大于或等于插入元素,然后将插入元素插入到队尾,同时因为我们删除了多个元素,所以我们给每一个元素增加一个编号,用来判断这个元素是否在滑动框内,不在的话就将其出队,然后队列的队首元素就是滑动框内的最大值,将这个值记录下来。

A代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<deque>
#include<cmath>

using namespace std;

const int N = 1e6 + 30;


struct node {
	int val;
	int id;
}arr[N];

deque<node> dqmax;

deque<node> dqmin;

int Max[N];

int Min[N];

int main() {

	int n, k;
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &arr[i].val);
		arr[i].id = i;
	}
	for (int i = 1; i <= k; i++) {
		if (dqmax.empty()) dqmax.push_back(arr[i]);
		else {
			while (!dqmax.empty()&&dqmax.back().val < arr[i].val) dqmax.pop_back();
			dqmax.push_back(arr[i]);
		}
		if (dqmin.empty()) dqmin.push_back(arr[i]);
		else {
			while (!dqmin.empty() && dqmin.back().val > arr[i].val) dqmin.pop_back();
			dqmin.push_back(arr[i]);
		}
	}
	Max[1] = dqmax.front().val;
	Min[1] = dqmin.front().val;
	for (int i = k+1; i <= n; i++) {
		while (!dqmax.empty() && dqmax.back().val < arr[i].val) dqmax.pop_back();
		dqmax.push_back(arr[i]);
		if (dqmax.front().id <= i - k) dqmax.pop_front();
		Max[i - k+1] = dqmax.front().val;
		while (!dqmin.empty() && dqmin.back().val > arr[i].val) dqmin.pop_back();
		dqmin.push_back(arr[i]);
		if (dqmin.front().id <= i - k) dqmin.pop_front();
		Min[i - k +1] = dqmin.front().val;
	}for (int i = 1; i <= n - k + 1; i++) {
		printf("%d ", Min[i]);
	}
	printf("\n");
	for (int i = 1; i <= n - k + 1; i++) {
		printf("%d ", Max[i]);
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值