当前位置:   article > 正文

leetcode239. 滑动窗口最大值(双向队列)

leetcode239. 滑动窗口最大值(双向队列)

题目

给你一个整数数组 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]
示例 3:
输入:nums = [1,-1], k = 1
输出:[1,-1]
示例 4:
输入:nums = [9,11], k = 2
输出:[11]

题解

解决滑动窗口问题一般有三种方法:
1.常规思路:暴力求解——N(nk)
时间复杂度较高,每个元素要被遍历k次
2.增减维护一个优先队列(最大堆)——N(nlogk)
给予一个完全二叉树来实现创库华东,队列入队一次(logk)出队指定元素一次(logk)
减少了重复判断,但是每次出入队还是较为复杂
3.通过单调Deque双端队列:——N(n)
这里我们可以参考一个篮球队长模型(不理解可以跳过):
从入学到毕业 高三队长,高一仍有机会, 高一队长,则高二高三则没有机会(直接抛弃)
实现步骤:
第一步,头部出队,清理超范围
第二步,移除尾部,在当前值前面的还小于当前值的元素
第三步,尾部入队,尾部范围正确
第四步,返回头部一一当前窗口最大值

在这里插入图片描述
即将入队的3大于对位的1,将1抛弃,并且入队3
在这里插入图片描述
3不小于即将入队的-1,则直接入队-1
在这里插入图片描述
同理-3入队(队首无出队:索引最小的元素此时还未超出窗口的最小范围)
在这里插入图片描述
将超出下限的3出队,在5入队前比较与-1,-3的大小,将其全部出队
在这里插入图片描述
继续将3入队(5 > 3不进行出队)
在这里插入图片描述
3和5都小于6,在6入队前先将3和5出队
在这里插入图片描述
最后6出队,7入队
在这里插入图片描述
单调的含义即,头部大尾部小,所以每次返回窗口的第一个元素即可。
代码如下:
python:

def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if not nums:return []
        window, res = [], []   #window存储窗口中元素的下标,res存储结果
        for i, x in enumerate(nums):
            #当window中第一个下标溢出时,将其踢出队列(左侧)
            if i >= k and window[0] <= i - k:
                window.pop(0)
            #加入下一个元素x前,将队尾小于x的元素出队(右侧)
            while window and nums[window[-1]] <= x:
                window.pop()
            window.append(i)
            if i >= k - 1:
                res.append(nums[window[0]])
        return res
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

c++:

class Solution {
public:
	vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(k==0)return {};
		vector<int>res;
		deque<size_t>window;
		/*Init K integers in the list*/
		for (size_t i = 0; i < k; i++) {
			while (!window.empty()  && nums[i] > nums[window.back()]) {
				window.pop_back();
			}
			window.push_back(i);
		}
		res.push_back(nums[window.front()]);
		/*End of initialization*/
		for (size_t i = k; i < nums.size(); i++) {
			if (!window.empty() && window.front() <= i - k) {
				window.pop_front();
			}
			while (!window.empty() && nums[i] > nums[window.back()]) {
				window.pop_back();
			}
			window.push_back(i);
			res.push_back(nums[window.front()]);
		}
		return res;
	}
};

  • 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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/458860
推荐阅读
相关标签
  

闽ICP备14008679号