首页 > 其他分享 >【单调队列】 单调队列的“扫描线”理解

【单调队列】 单调队列的“扫描线”理解

时间:2023-08-16 10:36:25浏览次数:47  
标签:队列 元素 扫描线 一段 序列 单调

【单调队列】 单调队列的“扫描线”理解

  “如果一个选手比你小还比你强,你就可以退役了。”——单调队列的原理

  • 比你强,而且比你影响时间更长。
  • 某种意义上,数学思维是生活中的思考的延伸。

  算法学习笔记(66): 单调队列。引用 Pecco 的算法笔记。

  在这里给出一种扫描线的理解。

图1

  我们以滑动窗口长度为 5,维护区间最大值为例子。

  图中横轴表示数组元素位置,纵轴表示数组元素大小,线表示每个数字的影响范围,对应记录的是长度为 k 的滑动窗口区间起点。因此,线段的右端点就是数组元素本身的位置。滑动窗口在图中仅仅需要标出起点的位置(一根竖线),就可以知道有哪些数字了。

  我们考虑后前后两段线。假如后一段大于等于前一段,那么后一段的影响未来范围比前一段更长,就可以在未来一直压着前一段。于是前一段没用了,弹出。(也就是说你预先考虑了一下未来的情况,然后弹出了)假如后一段小于前一段,虽然在过去和未来有限的时间里,前一段会压着后一段,但是后一段仍有不被压着的时候,因此后一段需要保留。

  当我们再直接观察队列中的弹出操作时候,就可以理解,弹出是因为之前的数影响范围被当前的更大的数字覆盖掉了。前面不弹出的是因为还有影响的可能。

  在这个问题中,序列本身是没有方向的,从左向右或者从右向左都行。我们进行滑动窗口的时候,需要规定一个方向。这个方向是无所谓的,但是一旦有了方向,这其中包含的已知到未知推导过程中前后顺序的维护信息,导致了单调队列的“覆盖”与弹出。剩下的“可能有贡献”的元素需要留着。删除不可能的,保留可能的,最后在某一时刻,从所有可能的中,选出确定的。

  为什么单调队列是单调的?我们考虑开始的时候用一个普通队列来维护,前后顺序是元素在序列中的顺序。每加入一个元素的时候,找一遍队列中的小于它的元素,删掉,再加入末尾(因为队列前后顺序和序列前后顺序是一样的)。这时候,查找就找这个队列里面的最大值。弹出照常。这两个操作现在还都是 \(O(k)\) 的。\(k\) 是滑动窗口长度。

  现在我们归纳地证一下。一个元素是有序的;对于新来的元素,改变一下操作顺序,先插入这个序列的正确排序的位置,再删除。有序序列删掉一些数还有序。于是 \(n\) 可以推 \(n+1\)。于是就都成立了。然后就有 \(O(1)\) 的取最大值和总和 \(O(n)\) 的插入删除操作了。\(n\) 是序列长度。

标签:队列,元素,扫描线,一段,序列,单调
From: https://www.cnblogs.com/l-cacherr/p/17633293.html

相关文章

  • 3.1 C++ STL 双向队列容器
    双向队列容器(Deque)是C++STL中的一种数据结构,是一种双端队列,允许在容器的两端进行快速插入和删除操作,可以看作是一种动态数组的扩展,支持随机访问,同时提供了高效的在队列头尾插入和删除元素的操作。Deque双向队列容器与Vector非常相似,它不但可以在数组尾部插入和删除元素,还可以在......
  • 3.1 C++ STL 双向队列容器
    双向队列容器(Deque)是C++STL中的一种数据结构,是一种双端队列,允许在容器的两端进行快速插入和删除操作,可以看作是一种动态数组的扩展,支持随机访问,同时提供了高效的在队列头尾插入和删除元素的操作。Deque双向队列容器与Vector非常相似,它不但可以在数组尾部插入和删除元素,还可以在......
  • 代码随想录算法训练营第十三天|单调数列:滑动窗口最大值(力扣239.)、优先级队列:前k个高
    单调数列:滑动窗口最大值(力扣239.)给定滑动窗口的范围,求每个滑动窗口范围内的最大值使用单调队列实现对于最大值数字前面的数字不存入数列,对于最大值数字后面的数字存入数列中单调队列中数字的大小呈递减顺序pop(value):如果窗口移除的元素等于单调队列的队口元素,则pop;否则什......
  • 单调栈(查找一个最大差值或查询某个位置左右两侧比他大(或小)的数的位置)
    leetcode121.买卖股票的最佳时机classSolution{public:intmaxProfit(vector<int>&prices){intans=0;vector<int>St;prices.emplace_back(-1);//为了结果的必然出现for(inti=0;i<prices.size();++i){......
  • Redis专题-队列
    Redis专题-队列首先,想一想Redis适合做消息队列吗?1、消息队列的消息存取需求是什么?redis中的解决方案是什么?无非就是下面这几点:0、数据可以顺序读取1、支持阻塞等待拉取消息2、支持发布/订阅模式3、重新消费4、消息不丢失5、消息可堆积那我们来看看redis怎么满足这些需......
  • 7.5 C/C++ 实现链表队列
    链表队列是一种基于链表实现的队列,相比于顺序队列而言,链表队列不需要预先申请固定大小的内存空间,可以根据需要动态申请和释放内存。在链表队列中,每个节点包含一个数据元素和一个指向下一个节点的指针,头节点表示队头,尾节点表示队尾,入队操作在队尾插入元素,出队操作在队头删除元素,队......
  • 循环队列
    为了避免当只有一个元素时,队头和队尾重合使得处理变得麻烦,所以引入两个指针front和rear。front即队头指针指向队头元素,rear即队尾指针指向队尾元素的下一个元素。这样当front等于rear是,不是队列中有一个元素,而是表示空队列。假设数组长度为5,空队列即初始状态如图所示,front和rear都......
  • 剑指 Offer 09. 用两个栈实现队列
    用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead操作返回-1)示例1:输入:["CQueue","appendTail","deleteHead","deleteHead","deleteHead"][[],[3],......
  • python 实现队列
    官方文档不推荐使用列表因为列表删除第一个元素会把剩余元素向左移一位速度很慢官方推荐的是collections下的deque 记录一下防止忘记 fromcollectionsimportdeque d=deque(‘内容’,maxlength)内容可以是推导式也可以直接写内容内容写在一起比如'123'结果会......
  • 单调队列模板
    好的,这是一个晴朗的夜晚。-苯荏水平不高甚至菜亖,博客仅仅写给自己避免自己忘记学了什么,也仅据我理解写出,不严谨,非常不严谨。单调队列。在原序列基础上,维护一个单调的序列。单调队列中的元素在原序列中的相对位置不变,且在单调队列中的元素是单调的。基本模板题:https://www.lu......