239. Sliding Window Maximum

Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.

For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.

Window position Max
[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

Therefore, return the max sliding window as [3,3,5,5,6,7].

Note:
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.

解题思路

这题受到求滑动窗口中位数的思想启发,可以使用有效元素概念。使用一个hash表保存被剔除的无效元素。然后使用最大堆去求窗口内的最大值,只要保证堆顶部的元素一定是有效的就可以了。

代码

class Solution {
public:
    vector maxSlidingWindow(vector& nums, int k) {
        unordered_map hash; 
        priority_queue> heap;
        vector res;
        
        for (int i = 0; i < nums.size(); i++) {
            if (i < k) {
                heap.push(nums[i]);
            } else {
                res.push_back(heap.top());
                heap.push(nums[i]);
                hash[nums[i - k]] ++;
                while (!heap.empty() && hash[heap.top()]) {
                    hash[heap.top()]--;
                    heap.pop();
                }
            }
        }
        if (!heap.empty()) {
            res.push_back(heap.top());
        }
        return res;
    }
};

当然,本题还有一种正解,那就是使用单调栈。单调栈,顾名思义,就是单调递增或者单调递减的栈。单调栈有很多应用,我们主要介绍在这里的应用。

首先,我们需要明白:

当取一个大小为k的值时,排在k前面的比k小的元素都不可能成为滑动窗口中的最大值。

由此,我们可以维护一个单调递减的单调栈:

Step1 : 判断栈底是否需要被弹出(即元素已经无效
Step2 :对于每一个进栈的元素,去除栈顶每一个比他小的元素,再将其入栈
Step3 :栈底的元素值即为当前窗口的最大值

由于我们的栈比较特殊,需要在栈底和栈顶操作,所以我们使用双端队列来实现:

class Solution {
public:
    vector maxSlidingWindow(vector& nums, int k) {
        deque dq;
        vector ans;
        for (int i=0; i=k-1) ans.push_back(nums[dq.front()]);
        }
        return ans;
    }
};

你可能感兴趣的:(239. Sliding Window Maximum)