zoukankan      html  css  js  c++  java
  • 单调队列(monotonic queue)列与单调栈的学习

    我们先回顾一下,无论是栈还是队列,我们把元素进入的一端称作“尾部”,另一端称作“头部”。

    对于栈,头部即是栈底,尾部即是栈顶。

    对于队列,头部对应队首,尾部对应队尾。

    单调栈

    我们都已经非常熟悉栈了,它具有先入后出的性质。而单调栈为了满足单调的要求,增加了一下性质:

    • 从栈顶到栈底的元素是严格递增 或 递减

    但这样和我们正常的流程有一定矛盾之处,如果栈中是5 4 3 2 1, 如果压入3要怎么办?原来我们只需要添加到栈尾即可,现在则需要将 3 2 1 弹出,再压入3,栈变成 5 4 3。

    注:弹出的元素我们直接舍弃掉。

    具体进栈过程

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

    一个单调递增栈的例子:

    进栈元素分别为3,4,2,6,4,5,2,3

    第i步操作结果
    1 3进栈 3
    2 3出栈,4进栈 4
    3 2进栈 4 2
    4 2、4出栈,6进栈 6
    5 4进栈 6 4
    6 4出栈,5进栈 6 5
    7 2进栈 6 5 2
    8 2出栈,3进栈 6 5 3

     单调队列

    对于单调队列,从单调栈的性质我们可以作推出:

    • 从队列头到队列尾的元素是严格递增

    添加元素e到队尾时,我们采取的解决方法同样是,先从队尾删去小于等于e的元素。

    注意,普通的队列queue是不支持从队尾删除的,我们需要使用双端队列deque,即有两个指针,一头一尾。

    队列的大小问题

    在谈及单调栈时,我略去了栈的大小这一个问题,因为在实际使用中,栈就通常没有大小的概念。而对于队列,它的大小就很重要了。

    如果队列满了,我们的解决方法是,将队列头的元素弹出,再添加新的元素到队列尾。

    具体入队过程

    • 对于单调递增队列,设当前准备入队的元素为e,从队尾开始把队列中的元素逐个与e对比,把比e大或者与e相等的元素逐个删除,直到遇到一个比e小的元素或者队列为空为止,然后把当前元素e插入到队尾。
    • 对于单调递减队列也是同样道理,只不过从队尾删除的是比e小或者与e相等的元素。

    一个递增单调队列的例子

    队列大小不能超过3,入队元素依次为3,2,8,4,5,7,4,6

    第i步操作结果
    1 3入队 3
    2 3从队尾出队,2入队 2
    3 8入队 2 8
    4 8从队尾出队,4入队 2 4
    5 5入队 2 4 5
    6 2从队头出队,7入队 4 5 7
    7 7从队尾出队,6入队 4 5 6
    8 6、5、4从队尾出队,4入队 4

    详细参考

  • 相关阅读:
    Halcon学习(车牌识别)
    Keil新建STM32工程(LED灯)
    Keil新建STM32工程(LED灯)
    Keil STM32F4xx_DFP.1.0.8.pack下载链接
    android 如何单独编译 img及作用
    Linux绑定硬件IRQ到指定SOC的CPU核
    sysrq: SysRq : HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e) memory-full-oom-kill(f)
    内核线程同步之completion
    kmalloc,vmalloc , malloc
    ARMv8 与 Linux的新手笔记(转载)
  • 原文地址:https://www.cnblogs.com/johnnyzhao/p/12841459.html
Copyright © 2011-2022 走看看