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

「这是我参与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 ( n k ) O(n*k) 有超时风险,所以需要想别的办法优化。

窗口队列

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

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

窗口 数组 最大值
窗口 1 [ 1 , 3 , 1 ] [1,3,-1] 3
窗口 2 [ 3 , 1 3 ] [3,-1,-3] 3
窗口 3 [ 1 3 5 ] [-1,-3,5] 5
窗口 4 [ 3 5 3 ] [-3,5,3] 5
窗口 5 [ 5 3 6 ] [5,3,6] 6
窗口 6 [ 3 6 7 ] [3,6,7] 7

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

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

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

通过枚举过程中维护 s t a c k stack 队列来快速获取【窗口】最大值 ;

难点2

如果最大值移出 s t a c k stack 队列,如何保证 s t a c k [ 0 ] stack[0] 是当前队列的最大值?

可以这样,在维护 s t a c k stack 队列时,将当前值 n u m s [ i ] nums[i] s t a c k [ s t a c k . l e n g t h 1 ] stack[stack.length-1] 比较

  • 如果 n u m s [ i ] > = s t a c k [ s t a c k . l e n g t h 1 ] nums[i] >= stack[stack.length-1] s t a c k [ s t a c k . l e n g t h 1 ] stack[stack.length-1] 删除,继续比较 n u m s [ i ] nums[i] s t a c k [ s t a c k . l e n g t h 1 ] stack[stack.length-1] ,直到 stack[stack.length-1] >= n u m s [ i ] nums[i] ;将当前值 n u m s [ i ] nums[i] 中的 i 放入 s t a c k stack 队列
  • 如果 n u m s [ i ] < s t a c k [ s t a c k . l e n g t h 1 ] nums[i] < stack[stack.length-1] ;放弃 i
  • 最后在 [k,nums.length] 区间,将 n u m s [ s t a c k [ 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;
};
复制代码

结语

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

おすすめ

転載: juejin.im/post/7067875684009377806