[路飞]_239. 滑动窗口最大值

1,669 阅读2分钟

「这是我参与2022首次更文挑战的第37天,活动详情查看:2022首次更文挑战

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]

题解

暴力枚举

通过枚举整个数组 O(n)O(n),再枚举寻找数组K长度最大值O(k)O(k),找出其中的最大值,时间复杂度O(nk)O(n*k) 有超时风险,所以需要想别的办法优化。

窗口队列

枚举整个数组O(n)O(n)的花费是必不可少的,现在就是如何优化在窗口中寻找最大值;有没有可能在枚举的时候计算出最大值?

分析一下数据 nums=[1,3,1,3,5,3,6,7],k=3nums = [1,3,-1,-3,5,3,6,7], k = 3

窗口数组最大值
窗口 1[1,3,1][1,3,-1] 3
窗口 2[3,13][3,-1,-3]3
窗口 3[135][-1,-3,5]5
窗口 4[353][-3,5,3]5
窗口 5[536][5,3,6]6
窗口 6[367][3,6,7]7

难点1
如何知道当前最大值需要移出【窗口】。

可不可以这样,记录最大值在原数组中的下标;并将下标存放到队列stackstack中。

枚举过程中如果当前下标当前下标 - stack[0]>=k >= k ; 需要将 stack[0]stack[0] 首位移出窗口

通过枚举过程中维护stackstack队列来快速获取【窗口】最大值 ;

难点2

如果最大值移出stackstack队列,如何保证 stack[0]stack[0]是当前队列的最大值?

可以这样,在维护stackstack队列时,将当前值 nums[i]nums[i]stack[stack.length1]stack[stack.length-1] 比较

  • 如果 nums[i]>=stack[stack.length1]nums[i] >= stack[stack.length-1]stack[stack.length1]stack[stack.length-1] 删除,继续比较nums[i]nums[i]stack[stack.length1]stack[stack.length-1] ,直到 stack[stack.length-1] >= nums[i]nums[i];将当前值 nums[i]nums[i] 中的 i 放入stackstack队列
  • 如果 nums[i]<stack[stack.length1]nums[i] < stack[stack.length-1] ;放弃 i
  • 最后在 [k,nums.length] 区间,将nums[stack[0]]nums[stack[0]] 存放到结果数组中
  • 返回结果数据

根据上述思路编辑代码如下:

var maxSlidingWindow = function (nums, k) {
  if (k === 1) return nums;
  const len = nums.length;
  const stack = [];
  let result = [];
  for (let i = 0; i < len; i++) {
    if (i - stack[0] >= k) stack.shift();
    while (nums[stack[stack.length - 1]] <= nums[i]) {
      stack.pop();
    }
    stack.push(i);

    if (i >= k - 1) {
      result.push(nums[stack[0]]);
    }
  }

  return result;
};

结语

作者水平有限,如有不足欢迎指正;任何意见和建议欢迎评论区浏览讨论