一、题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 输入: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:
1 2 输入:nums = [1], k = 1 输出:[1]
示例 3:
1 2 输入:nums = [1,-1], k = 1 输出:[1,-1]
示例 4:
1 2 输入:nums = [9,11], k = 2 输出:[11]
示例 5:
1 2 输入:nums = [4,-2], k = 2 输出:[4]
提示 :
1 ≤ nums.length ≤ 105
-104 ≤ nums[i] ≤ 104
1 ≤ k ≤ nums.length
二、题解 方法1: 暴力法
时间复杂度:O((n-k-1) * k),n 是 nums 的长度。总共 n-k-1 个滑动窗口,每个滑动窗口的找最大值的复杂度为 O(k),这种方式超出了题的时间限制。
空间复杂度:O(1)
1 2 3 4 5 6 7 var maxSlidingWindow = function (nums, k ) { const res = []; for (let i = 0 ; i <= nums.length - k; i++) { res.push(Math .max(...nums.slice(i, i + k))); } return res; };
方法2:滑动窗口 + 双端队列 1 2 3 4 5 题解: 双端队列: 每次push元素时,将队列中更小元素删除,直到不小时 每次pop元素时,如果是更小的元素在push时就已经删除了,只需要判断是否是头部最大值,是再删除一遍头部元素即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var maxSlidingWindow = function (nums, k ) { class slideWindow { constructor () { this .deque = []; } push(val) { while (this .deque.length > 0 && this .deque[this .deque.length - 1 ] < val) { this .deque.pop() } this .deque.push(val) } pop(val) { if (this .deque.length > 0 && this .deque[0 ] === val) { this .deque.shift() } } max() { return this .deque[0 ] } } let window = new slideWindow(); let res = []; const n = nums.length; for (let i = 0 ; i < n; i++) { if (i < k - 1 ) { window .push(nums[i]) } else { window .push(nums[i]); res.push(window .max()) window .pop(nums[i - k + 1 ]) } } return res; };