首页 > 其他分享 >单调队列与滑动窗口一

单调队列与滑动窗口一

时间:2023-04-03 23:46:05浏览次数:43  
标签:队列 最大值 元素 int 区间 滑动 单调

单调队列--滑动窗口最值问题

  • image-20230316225121476

image-20230316225030637

显然O(n^2)的时间复杂度是无法接受的
  • 我们先考虑滑动窗口滑动过程中最大值的问题

    • 过程即为我们想要维护每个滑动区间的最大值,当新插入一个元素前,我们把这个区间的第一个元素移除,插入新元素,并想在尽可能贴近O(1)的时间内得到该区间的最大值。

    • 这里是十分美妙的想法,借助一个单调队列来模拟上面的场景

      我们在队列头存放第一个预处理区间的最大值,然后降序存着一直到第一个区间末尾的元素(为什么要降序呢❓,这就是这里巧妙模拟的地方)

      后面每次区间移动新进入一个元素,如果该元素小于队尾元素,那么显然它不是最大值,而我们每次移动pop出去的队头元素就是该区间的最大值。

      如果该元素大于队尾元素,那么就不断向前删除队列中小于这个新元素的值(如果全部删除了,那么新插入的元素就是该区间新的最大值)

      还需要考虑的是如果几次插入的值都是小于区间最大值,那么何时队头需要出队,这里可以用pair<int,int> first存储该元素在数组中的下标,通过和当前窗口的的末尾下标做差来判断是否要让该队头元素出列.

      image-20230316231513200

        ```java
        #include<bits/stdc++.h>
        using namespace std;
        const int N = 1e6+10;
        int n,k;
        //用于存储最大值的下标
        deque<int>q;
        //存最小值xia'biao
        deque<int>p;
        int a[N];
        int main()
        {
            cin>>n>>k;
            for(int i=1;i<=n;i++) cin>>a[i];
           
                for(int i=1;i<=n;i++){
                if(!p.empty()&&p.front()<i-k+1){
                    p.pop_front();
                }
                while(!p.empty()&&a[i]<=a[p.back()]){
                    p.pop_back();
                }
                p.push_back(i);
                if(i>k-1) printf("%d ",a[p.front()]);
            }
            cout<<endl;
            for(int i=1;i<=n;i++){
                if(!q.empty()&&q.front()<i-k+1){
                    q.pop_front();
                }
                while(!q.empty()&&a[i]>=a[q.back()]){
                    q.pop_back();
                }
                q.push_back(i);
                if(i>k-1) printf("%d ",a[q.front()]);
            }
            
            return 0;
        }
        ```

标签:队列,最大值,元素,int,区间,滑动,单调
From: https://www.cnblogs.com/zhouylove/p/17284937.html

相关文章

  • 单调栈
    第一次听说单调栈是在cf上看到的,当时看的糊里糊涂,正好算法进阶指南上有单调栈,赶紧看看cf题:https://codeforces.com/contest/1795/problem/E单调栈,顾名思义,栈内的元素单调排序,当题目满足某些性质时,单调栈的先进后出性质显得尤为重要,滑动窗口模拟优先队列便是这样。书上的第一道......
  • 进程间通信 消息队列
    SystemVIPIPC:Inter-ProcessCommunication(进程间通讯)SystemV是早期的unix系统,曾经被称为AT&TSystem,是unix操作系统中比较重要的一个分支,现在Linux系统一般都支持SystemVIPCSystemVIPC对象共有三种消息队列共享内存信号量SystemVIPC是由内......
  • rabbitmq消息队列之持久化
    在生产过程中,难免会发生服务器宕机的事情,RabbitMQ也不例外,可能由于某种特殊情况下的异常而导致RabbitMQ宕机从而重启,那么这个时候对于消息队列里的数据,包括交换机、队列以及队列中存在消息恢复就显得尤为重要了。RabbitMQ本身带有持久化机制,包括交换机、队列以及消息的持久化。......
  • 详细解析Java异步线程处理队列任务工具类以及实战
    场景待入快速理解小场景描述:【一群人】来到【一个大厅】办理业务,大厅中有【多个窗口】给我们办理业务。每个人都有自己要办事情,处理过程需要消耗时间。大厅根据人群多少,开始窗口梳理。如果把“一群人”理解成一群待处理的n个【任务】,把这群人排成一个长队就形成了一个【任......
  • 数据结构 第三章 栈与队列
    之前期末考试,大部分都是二叉树,先根遍历之类的,还有一些辨析题目,一些很零碎的知识点,关于二叉树,这些的栈1.栈的概念首先对于线性表来说,线性表的插入和删除操作可以在任意的位置进行,而栈的插入和删除操作只允许在表的尾端进行。栈中,允许进行插入和删除操作的一端称为栈顶,另一端称......
  • 算法随想Day51【单调栈】| LC739-每日温度、LC496-下一个更大元素Ⅰ
    LC739.每日温度vector<int>dailyTemperatures(vector<int>&temperatures){intsize=temperatures.size();vector<int>result(size,0);vector<int>sta;sta.push_back(0);for(inti=1;i<size;++i){......
  • 算法随想Day52【单调栈】| LC503-下一个更大元素Ⅱ、LC42-接雨水
    LC503.下一个更大元素Ⅱ对于“每日温度”,相当于对nums数组,进行了两次遍历。用i%size所得余数作为下标,且循环的圈数为size*2vector<int>nextGreaterElements(vector<int>&nums){intsize=nums.size();vector<int>result(size,-1);vector<int>sta;......
  • 算法随想Day53【单调栈】| LC84-柱状图中最大的矩形
    intlargestRectangleArea(vector&heights){intresult=0;stackst;heights.insert(heights.begin(),0);heights.push_back(0);st.push(0);for(inti=1;i<heights.size();i++){if(heights[i]>heights[st.top()]){st.push(......
  • 对于数据链路层滑动窗口协议中窗口大小的总结
    3.4节中介绍了三种滑动窗口协议:1位滑动窗口协议、GBN协议、SR协议。1位滑动窗口协议本质上就是一种全双工的停等式协议,它的发送窗口和接收窗口大小都是1,在此不做赘述,我主要分析后两种协议的窗口大小。在SR协议中,窗口大小默认满足如下两个基本条件:发送窗口大小=接收窗口大小发......
  • 单调栈
    单调栈是一种和单调队列类似的数据结构。单调队列主要用于解决滑动窗口问题,单调栈则主要用于解决NGE问题(NextGreaterElement),也就是,对序列中每个元素,找到下一个比它大的元素。(当然,“下一个”可以换成“上一个”(对于序列的正序、反序遍历),“比它大”也可以换成“比他小”,原理不变。......