239. 滑动窗口最大值Leetcode

久未见 提交于 2020-03-05 01:38:01

239. 滑动窗口最大值

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

在这里插入图片描述

提示:

你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

进阶:

你能在线性时间复杂度内解决此题吗?

分析

  1. 记录时机:遍历vector ,i >= k - 1时开始记录窗口中的最大值
  2. 获取窗口中的最大值方法:
维护一个严格递减的数据结构
循环[i , i + k) ,比较得出最大值 O(n)
  • 采用方法二嵌套循环时间复杂度O(n2)
  • 因为我们只需要窗口中的最大值,严格递减的数据结构使用栈的特性,比当前遍历元素小的栈元素出栈,然后将当前遍历元素入栈,栈底为我们需要的最大值;在有序的数据结构中,随着窗口的移动,利用到队列的特性,当队首不在窗口中时,要把队首删除,维护有效的严格递减数据结构。双边队列deque满足上述栈和队列的所有能力,选用这个数据结构使问题简化,并降低时间复杂度为O(n)。
  1. 本题中,双边队列中可以存储数组下标,也可以存储数据元素。

C++实现

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> res;
        if(k == 0) return res;
        std::deque<int> win;
        for(int i = 0;i < nums.size();++i)
        {
            //严格递减,使用栈的特性
            while(!win.empty() && nums[i] > nums[win.back()])
            {
                win.pop_back();
            }
            win.push_back(i);

            //当队首不在窗口中时,要把队首删除
            if(i >= k && win.front() == i - k)
            {
                win.pop_front();
            }

            //开始记录窗口中的最大值的时机
            if(i >= k - 1)
            {
                res.push_back(nums[win.front()]);
            }
        }

        return res;
    }
};

Python3

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        res = []
        deq = collections.deque()
        for i,num in enumerate(nums):
            while deq and num > nums[deq[-1]]:
                deq.pop()
            deq.append(i)
            if i >= k and int(deq[0]) == i - k:
                deq.popleft()
            if i >= k - 1:
                res.append(nums[deq[0]])
        return res
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!