数据结构与算法之 leetcode 队列滑动窗口最大值算法 双端队列维护

数据结构与算法阿木 发布于 3 天前 1 次阅读


队列滑动窗口最大值算法(双端队列维护)详解

在数据结构与算法的学习过程中,滑动窗口问题是一个常见且具有挑战性的问题。滑动窗口算法通常用于处理固定大小窗口内的数据,并计算窗口内的最大值、最小值或其他统计信息。我们将探讨如何使用双端队列(deque)来维护一个滑动窗口,并实现一个高效的队列滑动窗口最大值算法。

概述

滑动窗口最大值问题可以描述为:给定一个数组 `nums` 和一个整数 `k`,找出每个大小为 `k` 的窗口中的最大值。例如,对于数组 `nums = [1,3,-1,-3,5,3,6,7]` 和 `k = 3`,我们需要找出以下窗口的最大值:


窗口 | 最大值


-----|------


[1, 3, -1] | 3


[3, -1, -3] | 3


[-1, -3, 5] | 5


[-3, 5, 3] | 5


[5, 3, 6] | 6


[3, 6, 7] | 7


为了解决这个问题,我们可以使用双端队列(deque)来维护一个窗口内的最大值。双端队列是一种具有两端都可以进行插入和删除操作的数据结构,非常适合用于实现滑动窗口算法。

双端队列

在Python中,可以使用 `collections.deque` 来实现双端队列。`deque` 提供了高效的插入和删除操作,非常适合用于实现滑动窗口算法。

python

from collections import deque

def max_sliding_window(nums, k):


if not nums or k <= 0:


return []

初始化双端队列和结果列表


dq = deque()


result = []

遍历数组


for i in range(len(nums)):


移除窗口外的元素


if dq and dq[0] == i - k:


dq.popleft()

移除窗口内的小于当前元素的元素


while dq and nums[dq[-1]] < nums[i]:


dq.pop()

将当前元素加入双端队列


dq.append(i)

当窗口大小达到k时,加入结果列表


if i >= k - 1:


result.append(nums[dq[0]])

return result


算法分析

时间复杂度

上述算法的时间复杂度为 O(n),其中 n 是数组 `nums` 的长度。这是因为每个元素最多被插入和删除一次,而双端队列的插入和删除操作都是 O(1) 的时间复杂度。

空间复杂度

算法的空间复杂度为 O(k),这是因为双端队列最多存储 k 个元素。

实例分析

让我们通过一个实例来验证上述算法的正确性。

python

nums = [1, 3, -1, -3, 5, 3, 6, 7]


k = 3


print(max_sliding_window(nums, k))


输出结果应该是:


[3, 3, 5, 5, 6, 7]


这与我们预期的结果一致。

总结

我们探讨了如何使用双端队列来维护一个滑动窗口,并实现了一个高效的队列滑动窗口最大值算法。通过使用双端队列,我们可以以 O(n) 的时间复杂度解决滑动窗口最大值问题,这对于处理大数据集非常有用。

扩展

滑动窗口算法可以扩展到其他问题,例如最小值、平均值等。双端队列也可以用于实现其他算法,如最近最少使用(LRU)缓存等。通过深入理解双端队列和滑动窗口算法,我们可以更好地解决各种实际问题。