返回
你所不知道的单调栈与单调队列(下)
前端
2023-12-07 08:14:34
在高速发展的技术领域中,不断更新的算法和数据结构层出不穷,对于技术从业者而言,掌握这些工具是至关重要的。单调栈和单调队列作为两个重要的数据结构,因其出色的特性而受到广泛应用。在这篇博文中,我们将深入探讨单调栈和单调队列,揭开它们鲜为人知的一面。
单调栈的本质
单调栈是一种遵循单调性原则的数据结构,即栈中元素的某个属性值(例如,数字大小)始终保持递增或递减的顺序。单调栈的出栈操作从栈顶(即最近添加的元素)开始,这与普通栈遵循的后进先出(LIFO)原则不同。
通过利用单调性,单调栈可以高效地解决一系列问题,例如:
- 求解矩形面积的最大值
- 寻找最近的较大元素
- 判定数组是否可以被重新排列成一个山脉数组
单调队列的奥秘
单调队列与单调栈类似,但其遵循的单调性原则适用于队列中元素的属性值。单调队列中的元素按照某种顺序排列,例如从队头到队尾递增或递减。与单调栈不同,单调队列的出队操作从队头开始,而入队操作在队尾进行。
单调队列的强大之处在于它的以下应用:
- 计算滑动窗口的最大值或最小值
- 判定数组是否可以被重新排列成一个谷底数组
- 求解最长连续子数组和
理解关键区别
虽然单调栈和单调队列都遵循单调性原则,但它们在出队方式上存在根本区别。单调栈的出栈操作从栈顶开始,而单调队列的出队操作从队头开始。这种差异导致了两者在具体应用场景上的不同。
此外,单调栈通常用于解决与最近元素或最大/最小值相关的操作,而单调队列则更适用于处理滑动窗口和数组排列等问题。
代码示例:求解滑动窗口的最大值
from collections import deque
def max_sliding_window(arr, k):
"""
:param arr: 输入数组
:param k: 滑动窗口大小
:return: 滑动窗口最大值的列表
"""
# 创建单调队列,存储数组元素索引
q = deque()
# 存储滑动窗口最大值的列表
max_values = []
for i in range(len(arr)):
# 如果队尾元素已不在窗口内,则弹出
while q and i - q[0] >= k:
q.popleft()
# 如果当前元素比队尾元素大,则弹出队尾元素
while q and arr[i] > arr[q[-1]]:
q.pop()
# 入队
q.append(i)
# 如果窗口大小已达到k,则将队首元素作为最大值
if len(q) == k:
max_values.append(arr[q[0]])
return max_values
结语
单调栈和单调队列是计算机科学中至关重要的数据结构,它们的特性使它们能够高效地解决一系列问题。通过理解它们的核心原理和应用场景,技术人员可以利用这些工具增强他们的算法设计能力。