Loading

单调队列问题

1:单调队列的概述

​ 前面我们了解了单调栈的的概念和单调栈的用途以及我们可以用单调栈解决什么样的问题,下面呢,我们就对比单调栈来解释一下单调队列的概念、用途,以及我们在解决什么问题的时候会用到单调队列。 ​ 我们都知道队列是很简单的一种数据结构,先进先出的逻辑顺序,符合某些问题的特点。单调队列顾名思义就是队列,只是利用了一些巧妙的逻辑,使得每次新元素入队列后,队列内的元素都保持有序(单调递增或单调递减)。上一篇我们讲到我们一般在解决比当前元素大或者小的下一个元素的时候会用到单调栈吗,(对比着栈是先进后出,而队列是先进先出)那么我们自然而然就可以想到,单调队列一般用来解决比当前元素大或者小的前一个元素的问题,也即是previous greater element 或者previous smaller element 相关问题,因为前一个更大的元素正好符合队列的基本定义,再加上单调性,就可以在O(n)时间复杂度内解决这类问题了,LeetCode中比较典型的单调队列问题如下。

2:LeetCode相关经典的题目

239. 滑动窗口最大值

862. 和至少为 K 的最短子数组

918. 环形子数组的最大和

1438. 绝对差不超过限制的最长连续

1499. 满足不等式的最大值

3:解决单调队列问题的一般代码模板

	for i, num := range nums {
        //维护队列的单调性
		for len(deque) > 0 && num >= nums[deque[len(deque)-1]] {
			deque = deque[:len(deque)-1]
		}
		deque = append(deque, i)
		//取队首的元素判断是否符合结果
		for deque[0] <= i-k {
			deque = deque[1:]
		}
		//更新结果
		if i >= k-1 {
			res = append(res, nums[deque[0]])
		}
	}

4:单调队列和单调栈的对比

 单调栈单调队列
解决问题 比当前元素更大(小)的下一个元素问题 比当前元素更大(小)的上一个元素问题
单调性 单调递增(减) 单调递增(减)
性质 先进后出 先进先出

5:解决单调队列问题的一般解题思路

​ 首先,我们在回顾一下单调队列是为了解决什么样的问题的,单调队列是为了解决比当前元素更大或者更小的上一个元素问题的,那么当我们遇到一个类似问题的时候我们要对比着单调队列已有的性质和解决方案分析问题,仔细的分析一下我们遇到的问题是否符合单调队列相关的性质(如果这个分析不出来的话,那就说明我们对单调队列相关的问题还不是太熟悉,按照LeetCode上面的问题类型多加练习和总结,一般在遇到类似相关问题就可以分析出此类问题应该用什么样的方式去解决),如果确定是属于单调队列的问题那么,我们就可以努力往单调队列的思路上去靠,然后利用单调队列的性质去解决此类问题。

​ 当然,我们解决问题的时候可能问题涉及的不只有单调队列这一个知识点,这就需要我们使用单调队列结合其他的知识来解决问题了,然而能熟练使用单调队列解决问题也不是解决一道或者两道问题就能深刻理解的,那么后续就需要我们多加练习和总结来巩固我们所学的知识点,为利用单调队列和其他知识点结合解决更复杂的问题夯实基础。

(以上的LeetCode中的问题比较经典,都是和单调队列相关的问题,还有和利用其他知识综合解决的问题,最好是按照顺序做一下,题解LeetCode已经写的非常的详细了,再次不多叙述关于具体题目的题解,本篇只是文档单纯的说一下关于单调队列问题的一些总结,具体的题解和参考LeetCode的官方题解)

posted @ 2022-02-19 11:58  Philosophy  阅读(130)  评论(0编辑  收藏  举报