单调队列

例题:

Poj 2823

给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数。

数列长度:N<=106,m<=N

对于单调队列,我们这样子来定义:

1、维护区间最值

2、去除冗杂状态 如上题,区间中的两个元素a[i],a[j](假设现在再求最大值)

若 j>i且a[j]>=a[i] ,a[j]比a[i]还大而且还在后面(目前a[j]留在队列肯定比a[i]有用,因为你是往后推, 核心思想 !!!)

3、保持队列单调,最大值是单调递减序列,最小值反之

4、最优选择在队首

单调队列实现的大致过程:

1、维护队首(对于上题就是如果队首已经是当前元素的m个之前,则队首就应该被删了,head++)

2、在队尾插入(每插入一个就要从队尾开始往前去除冗杂状态,保持单调性)

简单举例应用

数列为:6 4 10 10 8 6 4 2 12 14

N=10,K=3;

那么我们构造一个长度为3的单调递减队列:

首先,那6和它的位置0放入队列中,我们用(6,0)表示,每一步插入元素时队列中的元素如下

插入6:(6,0);

插入4:(6,0),(4,1);

插入10:(10,2);

插入第二个10,保留后面那个:(10,3);

插入8:(10,3),(8,4);

插入6:(10,3),(8,4),(6,5);

插入4,之前的10已经超出范围所以排掉:(8,4),(6,5),(4,6);

插入2,同理:(6,5),(4,6),(2,7);

插入12:(12,8);

插入14:(14,9);

那么f(i)就是第i步时队列当中的首元素:6,6,10,10,10,10,8,6,12,14

同理,最小值也可以用单调队列来做。

单调队列的时间复杂度是O(N),因为每个数只会进队和出队一次,所以这个算法的效率还是很高的。

注意:建议直接用数组模拟单调队列,因为系统自带容器不方便而且不易调试,同时,每个数只会进去一次,所以,数组绝对不会爆,空间也是S(N),优于堆或线段树等数据结构。

更重要的:单调是一种思想,当我们解决问题的时候发现有许多冗杂无用的状态时,我们可以采用单调思想,用单调队列或类似于单调队列的方法去除冗杂状态,保存我们想要的状态。

单调栈

例题:

问题描述

地上从左到右竖立着 n 块木板,从 1 到 n 依次编号,如下图所示。我们知道每块木板的高度,在第 n 块木板右侧竖立着一块高度无限大的木板,现对每块木板依次做如下的操作:对于第 i 块木板,我们从其右侧开始倒水,直到水的高度等于第 i 块木板的高度,倒入的水会淹没 ai 块木板(如果木板左右两侧水的高度大于等于木板高度即视为木板被淹没),求 n 次操作后,所有 ai 的和是多少。如图上所示,在第 4 块木板右侧倒水,可以淹没第 5 块和第 6 块一共 2 块木板,a4 = 2。

单调栈来求解的话,复杂度是O(n)

结合单调栈的性质:使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素。

顾名思义,单调栈就是栈内元素单调递增或者单调递减的栈,这一点和单调队列很相似,但是单调栈只能在栈顶操作。

单调栈有以下两个性质:

1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。

2、越靠近栈顶的元素越后进栈。

单调栈与单调队列不同的地方在于栈只能在栈顶操作,因此一般在应用单调栈的地方不限定栈的大小,否则可能会造成元素无法进栈。

元素进栈过程:对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。对于单调递减栈,则每次弹出的是大于e或者等于e的元素。

数据模拟木板倒水单调栈的入栈计算过程

思路:寻找比栈顶高的木板i,找到就出栈,不是就把木板i入栈,给出循环计数样例 10,5,8,12,6

从左往右扫描

栈为空,10入栈 栈:10 此时栈顶是10,也就是说要寻找比10大的木板

5比10小,5入栈 栈:5,10 此时栈顶是5,也就是说要寻找比5大的木板

8比5大,5出栈 栈:10

这个时候,第二个高度为5的木板右边比它高的木板已经找到了,是第三个木板8,所以5出栈,计算a2 = 3-2-1 = 0

8比10小,8入栈 栈:8,10 此时栈顶是8,也就是说要寻找比8大的木板

12比8大,8出栈 栈:10

第三个高度为8的木板右边比它高的木板已经找到了,是第四个木板12,8出栈,计算a3 = 4-3-1 = 0

12比10大,10出栈 栈:空

第一个高度为10的木板右边比它高的木板已经找到了,是第四个木板12,所以10出栈,计算a1 = 4-1-1 = 2

栈为空,12入栈 栈:12 此时栈顶是12,也就是说要寻找比12大的木板

6比12小,6入栈 栈:6,12 此时栈顶是6,也就是说要寻找比6大的木板

扫描完成结束

最后栈的结构是:6,12 栈顶为6

由于最右端竖立着一块高度无限大的木板,即存在第六块木板高度为无穷,所以剩余两块木板的算法如下 a5 = 6-5-1 =0

a4 = 6-4-1 = 1

sum = a1 + a2 +a3 +a4 +a5 = 3

因此本题可以在O(n)O(n)的时间内迎刃而解了。

从左往右将木板节点压栈,遇到比栈顶木板高的木板就将当前栈顶木板出栈并计算淹没的木板数,如此循环直到栈顶木板高度比当前木板高或者栈为空,然后将此木板压栈。木板全都压栈完成后,栈内剩余的木板都是右侧没有比它们更高的木板的,所以一个个出栈并计算ai=n+1-temp_id-1(用最右边无限高的木板减)。

单调队列java_单调队列单调栈相关推荐

  1. 单调队列java_浅谈单调队列优化dp

    单调队列,即单调的队列.有时用于优化1D/1D方程. 例题 Tyvj1305 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 输入一个长度为n的整数序列,从中 ...

  2. JAVA实现用两个栈来实现一个队列,完成队列的Push和Pop操作(《剑指offer》)

    最近在刷<剑指offer>里的编程题,但是网上关于<剑指offer>的解答多半是C或者C++的,而且官方(作者)也是在用C++进行讲解,这里自己用java写了一些题目的解答代码 ...

  3. 用栈实现队列和用队列实现栈

    首先需要使用上篇文章(用数组实现栈和队列)中的栈和队列两个类 1.栈实现队列:思路是有两个栈,一个用来放数据(数据栈),一个用来辅助(辅助栈).数据添加时,会依次压人栈,取数据时肯定会取栈顶元素,但我 ...

  4. 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。...

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. import java.util.Stack; public class Solution {      ...

  5. 算法:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。...

    算法:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型.<剑指offer> 利用栈来进行操作,代码注释写的比较清楚:首先判断两个栈是否是空的:其次当栈二 ...

  6. 栈和队列之用2个栈实现一个队列

    import java.util.Stack;/*** @author chenyu* 题目:编写一个类,用2个栈实现一个队列,支持队列的基本操作(add poll peek)* 思路:栈的特点是先进 ...

  7. java 栈 队列 接口_Java队列接口

    java 栈 队列 接口 介绍: 队列是FIFO(先进先出)抽象数据类型(ADT). 换句话说,按插入顺序将元素删除. java.util.Queue是Java 中的接口,并且从java.util.C ...

  8. 两个栈实现一个队列/两个队列实现一个栈

    http://blog.csdn.net/sinat_30472685/article/details/70157227 1两个栈实现一个队列 1.原理分析: 队列的主要操作有两个:入队操作和出队操作 ...

  9. java 先入先出,java_阻塞队列(FIFO先进先出)

    java_阻塞队列(FIFO先进先出) ArrayBlockingQueue:由数组结构组成的有界阻塞队列: LinkedBlockingQueue:由链表结构组成的有界阻塞队列(但大小默认值为:In ...

  10. 计算机二级循环队列知识点,考点!计算机二级考试公共基础知识冲刺复习笔记:栈、队列和循环队列...

    小编所收集到的相关计算机二级考试公共基础知识冲刺复习笔记:栈.队列和循环队列的资料 大家要认真阅读哦! 1.栈(Stack)又称堆栈. (1)栈是一种运算受限的线性表,其限制是仅允许在表的一端进行插入 ...

最新文章

  1. C语言语句单选题,C语言练习题
  2. 维护表读写的权限对象
  3. “贝叶斯网络之父”:不透明机器学习的局限性
  4. 基于FFmpeg H264 + G711A 音视频裸流合并 MP4文件 ( G711A 转 AAC)
  5. 以列表形式输出_python格式化输出总结
  6. 百度开源的分布式唯一ID生成器UidGenerator,解决了时钟回拨问题
  7. BZOJ3251: 树上三角形
  8. 编程让鼠标一直动_相见恨晚的效率提升工具,低价捡漏可以自定义编程快捷键的鼠标...
  9. 使用C++进行SVG开发
  10. linux版本即时通讯软件,Linux下即时通讯软件IM应用
  11. 软件测试包括哪些内容
  12. Packet Tracer使用说明
  13. OA系统集团化共享服务平台,全面协同、全面移动
  14. [Android自定义控件]自定义属性attrs.xml中format
  15. 排球-五一跑位(转)
  16. (CVPR 2020)3DSSD: Point-based 3D Single Stage Object Detector
  17. STM32——时钟系统RCC详细介绍
  18. 【文章思路、算法分析】Membership Inference Attacks Against Machine Learning Models
  19. 与表达式p =0等价的c语言表达式是,2015年3月全国计算机二级C语言选择第1套
  20. 《20个月赚130亿-YouTube创始人陈士骏自传》- 简评

热门文章

  1. Softing pnGate系列网关:将PROFIBUS总线集成到PROFINET网络
  2. 大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
  3. Java函数式编程与Lambda表达式
  4. 2021-08-16
  5. 小码哥教育笔记之VueDay01课程回顾
  6. java for 代表什么意思_java中for是什么意思?
  7. 默认关闭idea2020的注释doc的rendered view模式
  8. linux下twm切换gn,如何让vnc控制由默认的twm界面改为gnome?
  9. java vnc server_VNCServer 配置 及Vncview的使用
  10. java-net-php-python-java西藏文库计算机毕业设计程序