GDUT - 专题学习1 I - 滑动窗口
I - 滑动窗口
题目
原题来自:POJ 2823
给一个长度为 N 的数组,一个长为 K 的滑动窗体从最左端移至最右端,你只能看到窗口中的 K 个数,每次窗体向右移动一位,如下图:
你的任务是找出窗体在各个位置时的最大值和最小值。
输入格式
第 1 行:两个整数 N 和 K;
第 2 行:N 个整数,表示数组的 N 个元素(≤2×10^9);
输出格式
第一行为滑动窗口从左向右移动到每个位置时的最小值,每个数之间用一个空格分开;
第二行为滑动窗口从左向右移动到每个位置时的最大值,每个数之间用一个空格分开。
样例
Input
8 3 1 3 -1 -3 5 3 6 7
Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
数据范围与提示
对于 20% 的数据,K≤N≤1000;
对于 50% 的数据,K≤N≤10^5;
对于 100% 的数据,K≤N≤10^6。
思路
该题为单调队列的典型题。
如果纯暴力做的话,我们要从第一个元素一直历到第N个元素,每遍历一个元素都要再遍历框里面的元素,找出框里面的最大或最小值,这样的时间复杂是O(N×K)了,对于N和K都等于10^6时,时间已经爆了,所以我们要想一个更快速的做法,单调队列就是一个不错的选择。
就以样例中求每个框中的最小值为例:
单调队列首先要设头指针和尾指针(此指针非彼指针),还要建立一个队列数组,要注意的是队列数组中存的是元素的下标,而不是元素的值。
当框内元素还没到K个的时候,无法求得框内的最小值
当框移动到 i=3 的位置时
这时框内的最小值为-1,可存入队列中 ,这时候头指针指向了1,尾指针指向了2
当框移动到 i=4 的位置时
这时候新来的元素 -3 比头指针指向的 -1 还要小,所以要把 -1 踢出队列,踢出队列的方法就是让尾指针往前一格,这样下一次记录的时候就会将 -1 覆盖掉,就相当于把 -1 踢出去了
如此操作后队列就变成了
当框移动到 i=5 的位置时
这时候新来的元素是 5 ,比 -3 大,所以按从小到大的队列顺序来排应该排到后面,只需将 5 正常插入进队列即可
如此操作后队列就变成了
当框移动到 i=6 的位置时
这时候新来的元素是 3 ,比 -3 大,但比 5 要小,按顺序应该排到 5 前面,但是按照队列先进先出的特性,我们应该先把 5 踢出去,然后才能把 3 放进来,所以就按之前的操作一样,让尾指针往前走一格,然后将 3 存入即可
如此操作后队列就变成了
当框移动到 i=7 的位置时
要注意的是这个时候 -3 已经不在框里面了,所以我们要将 -3 给踢出去,方法就是将头指针向后走一格,这样 -3 就不在队列的范围里面了,然后新来的元素是 6 ,比 3 大,所以排到3的后面
如此操作后队列就变成了
有些同学看到这里可能就会有疑问了,之前的 -1 去哪了?为了解决这个问题,我们进行实时输出就行了
if (i >= k)
{cout << a[q[head]] << " ";
}
再次提醒一下,队列 q 里面存的是元素的下标,所以输出队列内元素的时候是输出 a[q[head]]
同样的,求题目中要求的最大值就令队列的排序规则反过来即可,该方法的时间复杂度为O(N)。
代码
#include<iostream>
using namespace std;
int n, k, a[1000005], q[1000005], head, tail;
int main()
{cin >> n >> k;for (int i = 1; i <= n; ++i){cin >> a[i];}head = 1, tail = 0;for (int i = 1; i <= n; ++i){if (head <= tail && i - k + 1 > q[head])//头指针肯定在尾指针前面{++head;}while (head <= tail && a[i] < a[q[tail]]){--tail;}q[++tail] = i;//这里存入的是元素的下标if (i >= k)//只要框到位置了,就直接输出当前状态的最小值{cout << a[q[head]] << " ";}}cout << endl;head = 1, tail = 0;//重置一下头、尾指针的位置for (int i = 1; i <= n; ++i){if (head <= tail && i - k + 1 > q[head]){++head;}while (head <= tail && a[i] >= a[q[tail]]){--tail;}q[++tail] = i;if (i >= k){cout << a[q[head]] << " ";}}return 0;
}
GDUT - 专题学习1 I - 滑动窗口相关推荐
- VINS-MONO学习笔记 [基于滑动窗口的非线性优化]
目录 1. 代码 2. ceres解析求导 3. ceres李代数加法代码实现 4. 预积分约束残差计算 5. 预积分雅克比计算 6. 视觉重投影约束 7. 滑动窗口边缘化 1. 代码 代码位置: v ...
- GDUT - 专题学习3 G - 食物链
题目 如图所示为某生态系统的食物网示意图,据图回答此题. 现在给你 n 个物种和 m 条能量流动关系,求其中的食物链条数. 物种的名称为从 1 到 n 的编号. mm 条能量流动关系形如 a1 b1 ...
- GDUT - 专题学习1 C - 马走日
C - 马走日 题目 马在中国象棋以日字形规则移动. 请编写一段程序,给定 n×m 大小的棋盘,以及马的初始位置 (x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. ...
- GDUT - 专题学习1 A - Red and Black
A - Red and Black 题目 There is a rectangular room, covered with square tiles. Each tile is colored ei ...
- GDUT - 专题学习1 D - 一维前缀和
D - 一维前缀和 题目 一天,在宿舍睡觉的你,突然梦到了游戏之神,他说:去玩<极限脱出>吧,这部作品的剧情和世界观绝对会带来很大的震撼,值得一玩. 对了,这部作品的第一代发布在nds上, ...
- GDUT - 专题学习2 C - 开餐馆
C - 开餐馆 题目 蒜头君想开家餐馆. 现在共有 n 个地点可供选择.蒜头君打算从中选择合适的位置开设一些餐馆.这 n 个地点排列在同一条直线上.我们用一个整数序列 m1,m2,...mn 来 ...
- 3.4 滑动窗口的卷积实现-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
←上一篇 ↓↑ 下一篇→ 3.3 目标检测 回到目录 3.5 Bounding Box 预测 滑动窗口的卷积实现 (Convolutional Implementation of Sliding Wi ...
- 计算机网络学习笔记(四)——差错控制、停等协议、回退N帧、选择性重传、滑动窗口、数据链路层HDLC、PPP协议、有限状态机
文章目录 前言 概念 一.差错控制 1.停等协议 2.回退N帧协议(GoBack_N,GB_N) 3.选择性重传协议(Selective Repeat,SR) 4.单帧确认和累计确认.捎带应答 二.链 ...
- 深度学习笔记(35) 滑动窗口的卷积实现
深度学习笔记(35) 滑动窗口的卷积实现 1. 卷积实现 2. 减少计算成本 1. 卷积实现 为了构建滑动窗口的卷积应用,首先要知道如何把神经网络的全连接层转化成卷积层 假设对象检测算法输入一个14× ...
最新文章
- 用 PHP 调用 MySQL 存储过程
- adb 重命名_Linux操作系统:三种最基本的文件重命名方法
- linux交换分区的文件格式为,LINUX的交换分区或交换文件SWAP的查看与维护
- 分布式链路追踪框架的基本实现原理
- Python内置数据类型之Dict
- java 生产者消费者_Java多线程:线程间通信—生产者消费者模型
- linux防火墙知识,Iptables防火墙 基础知识
- caffe之 Blob、Layer、Net
- 使用cmd命令创建vue(ivieiw)项目
- Java知识系统回顾整理01基础01第一个程序05Eclipse中运行Java程序
- 12306 官网硬卧下铺的选择
- mac airdrop 隔空投送 我可以发现别人,别人发现不了我。搜索不到。
- 电脑软件:推荐两款好用的文件重复检测软件,赶快给你的电脑瘦瘦身吧!
- STM8单片机的启动过程。
- 武林外传服务器时间修改,浅谈武林外传关于2021年4月29日大合区
- 如何关闭计算机自动关机设置方法,Win7电脑怎么取消自动关机?
- vm怎么上传镜像文件到服务器,vmware怎么添加iso镜像文件-vmware添加iso镜像文件的方法 - 河东软件园...
- 敏捷概念.Stacey矩阵
- 电脑调节屏幕亮度快捷键失灵の解决方案
- php 考试系统 倒计时,php实现倒计时效果_PHP