代码随想录算法训练营第十天(1)|239. 滑动窗口最大值

74 阅读2分钟

题目描述

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

代码示例

from collections import deque
from typing import List

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if not nums or k == 0:
            return []

        if k == 1:
            return nums

        deq = deque()
        result = []

        for i, num in enumerate(nums):
            # 移除不在窗口内的元素(从队列前端移除)
            while deq and deq[0] < i - k + 1:
                deq.popleft()

            # 移除所有小于当前元素的值(保持队列的单调递减)
            while deq and nums[deq[-1]] < num:
                deq.pop()

            # 添加当前元素的索引
            deq.append(i)

            # 从索引 k-1 开始添加每个窗口的最大值到结果中
            if i >= k - 1:
                result.append(nums[deq[0]])

        return result

# 测试示例
sol = Solution()
test_nums = [1,3,-1,-3,5,3,6,7]
test_k = 3
sol.maxSlidingWindow(test_nums, test_k)  # 应该返回窗口最大值的列表


在面对这样的算法问题时,我的最初想法是采用一个较为直观的方法:初始化一个空队列,这个队列的最大长度设置为 k。这样,当队列达到这个长度时,我会遍历队列来找出其中的最大值。然后,根据滑动窗口的移动,执行出队和入队的操作,以保持队列的长度恒为 k。这种方法虽然直接,但效率并不是最佳的,尤其是在处理大数据集时。

然而,在仔细阅读代码和相关的随想录之后,我意识到使用单调队列是一个更高效的策略。单调队列的核心优势在于它能够在常数时间内给出当前窗口的最大值。这是通过维持队列中元素的单调递减顺序实现的,确保队列的头部始终是当前窗口的最大值。这种方法避免了每次窗口滑动时对整个窗口进行遍历,从而大大提高了算法的运行效率。通过这种方式,我可以更加高效地处理大量数据,特别是在面对大规模数据集时,这种优化显得尤为重要。