单调队列初步「建议收藏」

单调队列初步「建议收藏」
一直弄不明白单调队列是什么,在网上也找不到易懂的介绍。最后结合别人博客上的介绍和程序看才理解是怎么回事。
我们从最简单的问题开始:
给定一个长度为N的整数数列a(i),i=0,1,…,N-1和窗长度k.
要求:
     f(i)=max{a(i-k+1),a(i-k+2),…,a(i)},i=0,1,…,N-1
问题的另一种描述就是用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值。
解法一:

大家好,又见面了,我是你们的朋友全栈君。

一直弄不明白单调队列是什么,在网上也找不到易懂的介绍。最后结合别人博客上的介绍和程序看才理解是怎么回事。

我们从最简单的问题开始:

给定一个长度为N的整数数列a(i),i=0,1,…,N-1和窗长度k.

要求:

      f(i) = max{a(i-k+1),a(i-k+2),…, a(i)},i = 0,1,…,N-1

问题的另一种描述就是用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值。

解法一:

很直观的一种解法,那就是从数列的开头,将窗放上去,然后找到这最开始的k个数的最大值,然后窗最后移一个单元,继续找到k个数中的最大值。

这种方法每求一个f(i),都要进行k-1次的比较,复杂度为O(N*k)。

那么有没有更快一点的算法呢?

解法二:

我们知道,上一种算法有一个地方是重复比较了,就是在找当前的f(i)的时候,i的前面k-1个数其它在算f(i-1)的时候我们就比较过了。那么我们能不能保存上一次的结果呢?当然主要是i的前k-1个数中的最大值了。答案是可以,这就要用到单调递减队列。

单调递减队列是这么一个队列,它的头元素一直是队列当中的最大值,而且队列中的值是按照递减的顺序排列的。我们可以从队列的末尾插入一个元素,可以从队列的两端删除元素。

1.首先看插入元素:为了保证队列的递减性,我们在插入元素v的时候,要将队尾的元素和v比较,如果队尾的元素不大于v,则删除队尾的元素,然后继续将新的队尾的元素与v比较,直到队尾的元素大于v,这个时候我们才将v插入到队尾。

2.队尾的删除刚刚已经说了,那么队首的元素什么时候删除呢?由于我们只需要保存i的前k-1个元素中的最大值,所以当队首的元素的索引或下标小于i-k+1的时候,就说明队首的元素对于求f(i)已经没有意义了,因为它已经不在窗里面了。所以当index[队首元素]<i-k+1时,将队首元素删除。

 

从上面的介绍当中,我们知道,单调队列与队列唯一的不同就在于它不仅要保存元素的值,而且要保存元素的索引(当然在实际应用中我们可以只需要保存索引,而通过索引间接找到当前索引的值)。

为了让读者更明白一点,我举个简单的例子。

假设数列为:8,7,12,5,16,9,17,2,4,6.N=10,k=3.

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

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

0:插入8,队列为:(8,0)

1:插入7,队列为:(8,0),(7,1)

2:插入12,队列为:(12,2)

3:插入5,队列为:(12,2),(5,3)

4:插入16,队列为:(16,4)

5:插入9,队列为:(16,4),(9,5)

。。。。依此类推

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

程序代码如下:

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153008.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • partial conflict_conditional tense

    partial conflict_conditional tenseTableofContents定制FilterCell1.引言1.1.定制Droplist过滤器Cell示例定制FilterRowsCallback1.引言1.1.定制FilterRowsCallback示例Form指南1.引言1.1.JSP1.1.1.Form特性的技术说明1.1.2.Checkbox1.1.3.CustomCell1.1.4.

    2022年8月20日
    6
  • 微信表情 代码_微信暗语代码大全

    微信表情 代码_微信暗语代码大全/::)笑话/::~撇嘴/::B色/:,@f奋斗/:heart爱心/:showlove嘴唇/:cake蛋糕/:gift礼物/:handclap鼓掌/::*亲亲/:rose玫瑰/:kiss献吻/:love爱情/:okOK/:lvu爱你/:jj勾引/:@)抱拳/:sh…

    2025年8月15日
    1
  • centos sqlite3安装及简单命令

    centos sqlite3安装及简单命令

    2021年7月18日
    75
  • 单片机好学还是plc好学_单片机出路

    单片机好学还是plc好学_单片机出路相信很多学电气工程专业的都会学习PLC,我当初也是电气工程专业,主要学的三菱PLC,后面也玩了下西门子的。当时觉得还挺神奇,也对编程比较感兴趣,不过学校学得太简单了,基本让你编个梯形图控制电机就算是毕业了。后来我就转去做单片机开发了,感觉比PLC更好玩,因为成本低,灵活性也高,可玩性自然也更高。最近我们无际单片机编程也有几个学员是做PLC转行过来学单片机的。我没从事过PLC的工作,根据他们描述,PLC的工资其实也还行,基本也能过万,但是就是出差太频繁,一年300天在外面出差。如果是单身寡

    2022年8月31日
    2
  • 滑动窗口 leetcode_滑动窗口的概念

    滑动窗口 leetcode_滑动窗口的概念原题链接给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。示例 1:输入:nums = [1,3,-1,-3,5,3,6,7], k = 3输出:[3,3,5,5,6,7]解释:滑动窗口的位置 最大值————— —–[1 3 -1] -3 5 3 6 7

    2022年8月9日
    7
  • Linux内核移植_rom内核移植

    Linux内核移植_rom内核移植这两天在友善的tiny210的实验板上移植了linux内核,正好和大家分享,同时也算是做个记录吧!首先介绍一下开发环境吧,这个在做移植的时候还是挺重要的。主机linux:Fedora9 安装在VMware虚拟机上;开发板 :友善的tiny210,256M的FLASH;移植linux:LINUX-3.3.5;交叉编译环境:arm-linux-gcc-4.4.3这个是友善24

    2022年9月24日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号