[2025-09-26] Leetcode 239. 滑动窗口最大值(未得到最优解)

题目

239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
 
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
————— —–
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1
输出:[1]
 
提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

我的代码(Python)

version 1

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        result = []
        print(f'k: {k}')
        if k == 1:
            result = nums
        elif k % 2 == 0:
            semi_result = self.maxSlidingWindow(nums, k // 2)
            for i in range(len(nums) - k + 1):
                result.append(max(semi_result[i], semi_result[i + k // 2]))
        else:
            semi_result1 = self.maxSlidingWindow(nums, k // 2)
            semi_result2 = self.maxSlidingWindow(nums, k - k // 2)
            for i in range(len(nums) - k + 1):
                result.append(max(semi_result1[i], semi_result2[i + k // 2]))
        return result

暴力解法肯定是不行的,O(n)O(k)。这样大概可以化简到O(n)O(lgk),不过重复计算过多,实现前就推测应该不行。
结果不出所料,超时了。

version 2

class Solution:
    def calculateResult(self, nums: List[int], k: int, inter_results: List[List[int]]) -> None:
        if len(inter_results[k - 1]) > 0:
            return inter_results[k - 1]
        if k % 2 == 0:
            m = k // 2
            self.calculateResult(nums, m, inter_results)
            for i in range(len(nums) - k + 1):
                inter_results[k - 1].append(max(inter_results[m - 1][i], inter_results[m - 1][i + m]))
        else:
            m = k // 2
            n = k - m
            self.calculateResult(nums, m, inter_results)
            self.calculateResult(nums, n, inter_results)
            for i in range(len(nums) - k + 1):
                inter_results[k - 1].append(max(inter_results[m - 1][i], inter_results[n - 1][i + m]))

    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        inter_results = [nums] + [[] for _ in range(k - 1)]
        print(f'inter_results: {inter_results}')
        self.calculateResult(nums, k, inter_results)
        return inter_results[k - 1]

虽然通过了,但是时间和空间都在末5%左右。
迭代虽然比较容易理解和实现,但是在效率上并不好。
只是结果这么差,感觉上不是这个问题,还是方向本身有误。

            for i in range(len(nums) - k + 1):
                inter_results[k - 1].append(max(inter_results[m - 1][i], inter_results[m - 1][i + m], nums[i + k - 1]))

把计算处奇数的计算方式优化如上,时间上没有多少提升,内存上略有优化,可见还是方向不对。

点评

参考了官方的答案。官方给出了三种方式,我的方案实际上算是第三种方案,预处理。
官方的第一种答案又是惯例的标准库中的数据结构和函数的使用,排序、插入和删除(此处是使用最大堆)都达到最优化方案。对python来说是heapq。
不过第二种答案单调双端队列确实非常巧妙,不是很容易想得到的。简单来说就是保证队列里的每一个值,在往前最大k – 1,往后最大k的范围内是最大的。

发表评论

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

滚动至顶部