LeetCode 239. 滑动窗口最大值 (堆、单调队列)

滑动窗口最大值
标题即题意,滑动窗口经典例题。
暴力法时间复杂度: O ( ( n − k ) ∗ k ) O((n-k)*k) O((nk)k)
主要耗时的是要在窗口的k个元素里通过遍历挑出最大值。

  • 用堆去优化,multiset实现,时间复杂度: O ( ( n − k ) ∗ l o g ( k ) ) O((n-k)*log(k)) O((nk)log(k))
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        multiset<int> vis;
        vector<int> ans;
        int n = nums.size();
        for(int i=0;i<k-1;i++){
            vis.insert(nums[i]);
        }
        for(int i=k-1;i<n;i++){
            vis.insert(nums[i]);
            ans.push_back(*vis.rbegin());
            vis.erase(vis.find(nums[i-k+1]));
        }
        return ans;
    }
};
  • 单调队列,用一个队列去存储这个窗口里有用的元素
    那么什么是无用的元素呢?
    比如: [5 4 2 1] 6 1 2 8
    窗口里一开始有四个元素: 5 4 2 1,但是一旦窗口右移一位,把6入队后,5 4 2 1 都不可能成为最大值了,所以要从队列的尾部开始删去比这个数更小的数
    时间复杂度: O ( n ) O(n) O(n)(每个元素最多出一次队)
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k){
        vector<int> ans;
        deque<int> dq;
        int n = nums.size();
        for(int i=0;i<n;i++) {
            //从队列的尾部开始删去比这个数更小的数。
            while(!dq.empty() && dq.back()<nums[i]){
                dq.pop_back();
            }
            dq.push_back(nums[i]);
            if(i>=k-1) {
                ans.push_back(dq.front());
                if(nums[i-k+1] == dq.front()){
                    dq.pop_front();
                }
            }
        }
        return ans;
    }
};

你可能感兴趣的:(LeetCode,#,LC滑动窗口)