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

单调队列初步「建议收藏」
一直弄不明白单调队列是什么,在网上也找不到易懂的介绍。最后结合别人博客上的介绍和程序看才理解是怎么回事。
我们从最简单的问题开始:
给定一个长度为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)
上一篇 2022年6月25日 上午10:00
下一篇 2022年6月25日 上午10:16


相关推荐

  • Ubuntu安装与卸载tensorflow

    Ubuntu安装与卸载tensorflow安装sudopipinstalltensorflow-gpu==1.2卸载sudopipuninstalltensorflow-gputensorflow1.2.0配cuda8.0、cudnn5.1

    2022年6月22日
    81
  • 数字音频编辑的基本流程_数字音频编辑

    数字音频编辑的基本流程_数字音频编辑为什么会有SampleRate和BitdepthSampleRate就是采样率Bitdepth就是位深度不管在什么应用场合,只要是关于数字音频的这两个参数必然跑不了,网上的问答多为如何设置这两个参数,在何种使用场景使用哪种采样率和位深度最好,但对做数据处理的必须知道这两个值怎么设定,才能在特殊场合提高处理速度牺牲精度或是提高精度牺牲处理速度。SampleRate简单来说,Sample…

    2022年10月17日
    5
  • 智谱 GLM-4.6 旗舰 AI 模型发布:代码能力全面进阶,适配寒武纪、摩尔线程芯片

    智谱 GLM-4.6 旗舰 AI 模型发布:代码能力全面进阶,适配寒武纪、摩尔线程芯片

    2026年3月12日
    2
  • pyyaml使用_pam模块

    pyyaml使用_pam模块pyyaml模块

    2025年11月11日
    6
  • Java strictfp[通俗易懂]

    Java strictfp[通俗易懂]Javastrictfp关键字的作用strictfp关键字可以应用于方法,类和接口。strictfp关键字的非法代码Javastrictfp关键字确保您将在每个平台上获得相同的结果,如果在浮点变量中执行操作。不同平台的精度可能不同,这就是为什么java编程语言提供了strictfp关键字,它用于在每个平台上获得相同的结果。所以,现在我们就可以更好的控制浮点数据类型运算了。strictf…

    2025年8月25日
    4
  • 三种线程安全的List

    三种线程安全的List在单线程开发环境中 我们经常使用 ArrayList 作容器来存储我们的数据 但它不是线程安全的 在多线程环境中使用它可能会出现意想不到的结果 多线程中的 ArrayList 我们可以从一段代码了解并发环境下使用 ArrayList 的情况 publicclassC publicstatic String args throwsInterr List Integer l Integer

    2026年3月18日
    2

发表回复

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

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