LeetCode|Sliding Window Maximum

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.

思路:

  • 维护一个大小为k的堆或者multiset,然后每次插入或者删除都是O(log k)的,整体复杂度就是O(nlog k)
  • 做过Min Stack(参考文章)的人应该可以想到另一种O(n)的方法来模拟。假设window左边是栈顶,每次要执行出栈。那么这次是从栈底,即窗口右边,来添加元素。压入栈底那就好比是之前就已经压入栈顶的元素,那么应该满足该元素之上的其他元素都不小于它。 用deque来模拟,栈顶是front,即左边。栈底是back,右边。压入栈底时要保证左边的元素都不小于它,所以deque从左至右是一个递减序列。

至于复杂度为什么是O(n):找最大值、pop每次的操作是O(1)很好理解。push因为比x小的数会被pop,所以后续不会参与比较了。

class myDeque{
    public:
    void push_back(int x){
        while(!deq.empty() && deq.back() < x){
            deq.pop_back();
        } deq.push_back(x);
    }
    void pop_front(){
        deq.pop_front();
    }
    int getMax(){
        return deq.front();
    }
    private:
    deque<int> deq;
};
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> ans;
        myDeque deq;
        for(int i = 0; i < k-1; i++) deq.push_back(nums[i]);
        for(int i = k-1; i < nums.size(); i++){
            deq.push_back(nums[i]);
            ans.push_back(deq.getMax());
            if(nums[i-k+1] == deq.getMax()){
                deq.pop_front(); // excute pop in special case
            }
        } return ans;
    }
};

你可能感兴趣的:(LeetCode)