文章目录

    • 题目分析
      • 初始思路
      • 单调队列优化的思路
      • 代码1:数组模拟单调队列的代码
  • 代码2:deque容器实现

能用到单调队列的情景比较有限: 1.典型的有滑动窗口的最值, 2.找到里它最近的比它大(小)的元素。

题目大意:滑动窗口求最值:您的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

题目分析

初始思路

如果不考虑单调队列优化,普通的做法我们如何思考的呢?

首先是实现窗口的滑动: 维护一个队列,新元素插入到队头,队尾元素删除掉,实现滑动窗口右移一位。 n次操作

其次是求窗口内的最值: 遍历一遍 k次操作

朴素做法总的时间复杂度是O(n×k)O(n\times k)O(n×k)

以上是暴力的做法,也是最容易想到的做法。

单调队列优化的思路

以求最小值为例:该数组为[1 3 -1 -3 5 3 6 7],k为3。

开始时[1 3 -1] 后移一位变成 [ 3 -1 -3] ,如果 -3 是最小值,那么它前面的 -1 和 3就再也用不到了,是多余的,可以删掉。 删掉多余的元素之后, 元素就有了单调性!找滑动窗口内的最小值就是队头元素,时间复杂度为O(1) ,那么这道题单调队列总的时间复杂度就是O(n).

代码1:数组模拟单调队列的代码

思路说完了,上代码和代码解释。

找最小值的思路

一个队列维护当前窗口中的单调上升的情况。当前窗口的最小值就是队头q[tt]。

i表示当前窗口的最右边下标,k表示窗口长度,则窗口最左边下标为i-k+1。即当前滑动窗口 为[队首,队尾]=[ i-k +1 , i].

队列数组q中存放的是点的下标,对于数组模拟的队列q而言,hh表示队头,tt表示队尾,初始化时hh=0,tt=-1,如果hh<=tt表示队列不空。

何时删掉队头元素 ?因为枚举的是右端点,受限的就是左端点。当q队首的值(q中存的是下标)q[hh]小于当前窗口最左边下标的时候:q[hh]<i-k+1此时队头元素删掉,即hh++。

#include<iostream>
using namespace std;
const int maxn=1e6+10;
int a[maxn],q[maxn];
int main(){int n,k;scanf("%d%d",&n,&k);for(int i=0;i<n;i++) scanf("%d",&a[i]);int hh=0,tt=-1;//队头(在左边)和队尾(在右边)for(int i=0;i<n;i++ ){//区间终点是i  那么整个区间是 [   i-k+1,i]//判断队头是否划出窗口,每次查看一次if(hh<=tt&&q[hh]<i-k+1) hh++;//q存的是下标 while(hh<=tt&&a[q[tt]]>=a[i]) tt--;// 队列不空,且新来元素更小,把前面所有冗余(比它大的)都清理掉q[++tt]=i;//把当前最小的放进来//当第一次满足窗口长度k时,往后随着i的递增,每次都要输出最小值,因为窗口在移动if(i>=k-1) printf("%d ",a[q[hh]]);//a【q[]】严格单调上升的最小值,是队头q[hh]}puts("");//输出空格return 0;}

同理可找最大值,维护一个队列单调递减,这样队首就是滑动窗口中的最大值。

题目链接:acwing154滑动窗口

ac代码

#include<iostream>
using namespace std;
const int maxn=1e6+10;
int a[maxn],q[maxn];
int main(){int n,k;scanf("%d%d",&n,&k);for(int i=0;i<n;i++) scanf("%d",&a[i]);//找最小值int tt=-1,hh=0; //队头hh,队尾 ttfor(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+1>=k) printf("%d ",a[q[hh]]);}puts("");//找最大值tt=-1,hh=0;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+1>=k) printf("%d ",a[q[hh]]);}puts("");return 0;}

代码2:deque容器实现

acwing中的ac代码

#include<bits/stdc++.h>
using namespace std;const int N=1000010;
int a[N];
deque<int> q;
int main(){int n,k;cin>>n>>k;for(int i=0;i<n;i++)cin>>a[i];for(int i=0;i<n;i++){if(q.size() && q.front()<i-k+1) q.pop_front();while(q.size() && a[q.back()]>=a[i]) q.pop_back();q.push_back(i);if(i>=k-1) cout<<a[q.front()]<<" ";}cout<<endl;q.clear();for(int i=0;i<n;i++){if(q.size()&& q.front()<i-k+1) q.pop_front();while(q.size()&& a[q.back()]<=a[i]) q.pop_back();q.push_back(i);if(i>=k-1) cout<<a[q.front()]<<" ";}}

单调队列板子:求滑动窗口中最大值和最小值相关推荐

  1. 求滑动窗口中的最大值和最小值

    滑动窗口: 一般使用双指针算法,左指针l和右指针r之间的空间称为窗口,由于指针是不断移动的,从而窗口也可以移动,称为滑动窗口. 滑动窗口的最值: 由于窗口是移动的,移动的过程中有新元素的加入也有旧元素 ...

  2. OpenCV求(图像)矩阵中最大值,最小值函数minMaxLoc() vs minMaxIdx()

    转载请注明出处. 文章地址:https://blog.csdn.net/duiwangxiaomi/article/details/97937706?spm=1001.2014.3001.5501   ...

  3. 用c语言求一组数中最大值和最小值,用c语言求一组数组的最大值以及最小值

    #include//stdio.h是c的标准的i/o库,是以函数的方式向buffer写入或读取字符,iostream.h是c++的标准i/o库,引入了输入/输出流的概念,是一个类库,是以类方法从str ...

  4. 求一维数组中最大值和最小值

    #include<stdio.h> int niubi_max(int a[]);    // 函数声明类型与定义类型应该相同,不能声明是 int,定义是 int a[] int niub ...

  5. c语言求n个数中最大值和最小值,C语言:从键盘输入n个数,求最大值和最小值(用数组)...

    满意答案 zxyev 2020.07.01 采纳率:51%    等级:7 已帮助:608人 #include #include #define ARR_LEN 255 /*数组长度上限*/ #def ...

  6. Sliding Window 单调队列解决--经典滑动窗口问题--求窗口的最大值最小值

    http://poj.org/problem?id=2823 这就要用到单调递减或单调递增队列来实现,它的头元素一直是队列中的最小值或最大值.我们可以从队列的末尾插入一个元素,可以从队列的两端删除元素 ...

  7. Leetcode1696. 跳跃游戏 VI[C++题解]:dp和单调队列求滑动窗口最值

    文章目录 题目分析 题目链接 单调队列板子链接 Deque知识补充 题目分析 题目重述:给定一个数组(有正数有负数)和一个步长k,从下标0处开始往前跳,每次最多往前跳k步.求跳到最后一个位置,得分之和 ...

  8. 环形数组队列求滑动窗口最大值

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位.返回滑动窗口中的最大值. 示例: 输入: nu ...

  9. leetcode59题:滑动窗口的最大值(用双端队列实现)

    题目描述: 给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值. 示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5, ...

最新文章

  1. DFT实际应用-User-Defined Test Points Example
  2. RedisDeskTopManager连接时提示:can't nonnect to redis-server
  3. NYOJ 79 拦截导弹
  4. 受大厂们青睐的Web前端工程师需要掌握的3项能力!
  5. ajax实现highchart与数据库数据结合完整案例分析(三)---柱状折线图
  6. CodeForces - 1497D Genius(dp)
  7. Spring Boot 设置启动时banner
  8. Leetcode142. Linked List Cycle II环形链表2
  9. python实现异步的原理_一篇文章理解Python异步编程的基本原理
  10. ASP.NET MVC 添加Model并连接到本地数据库
  11. sht20中写用户寄存器_SHT20最新数字温湿度传感器芯片 程序
  12. tft液晶屏接口概述及信号类型
  13. keil5新建STM32工程文件--实践篇手把手教学(以STM32F103为例)
  14. Centos升级Chrome浏览器
  15. 数据库连接查找不到数据库_查找具有受保护的健康信息的数据库
  16. JavaScript高级编程(一)——基本概念
  17. GB2312和BIG5,Unicode/UTF8等编码之间的互相转化
  18. mysql 漏洞排查_MySQL最新漏洞分析_MySQL
  19. 你这一生还能陪妈妈几天?来看看
  20. Python地理数据分析常识

热门文章

  1. 第三章:3.栈和队列 -- 栈与递归的实现
  2. iOS web与JS交互
  3. ubuntu vsftp安装
  4. linux怎么调整运行模式,如何手动设置修改X-Window的显示模式-linux思想
  5. STM32 基础系列教程 30 - 文件系统
  6. STM32 基础系列教程 27 - USB_HID
  7. ATPG Practice ATPG Practice II
  8. 基础篇-verilog-实现循环左移右移
  9. axure中的中继器
  10. 【发布】温度监测报警器v1.3a稳定版!