算法day33 滑动窗口的最大值

题目描述

思路:单调队列
本题要获得滑动窗口的最大值,我们若是想用双指针暴力解法,在k较大以及数据量较大时会超时,时间复杂度为O(n*k),所以我们应该另寻他法。注意滑动窗口在每一轮循环中会将这一轮的第一个位置的元素抛出,然后在窗口尾部引入一个新的元素。那么我们应该这样考虑,每一轮更新强制性地将上一轮的窗口首位置元素抛出,随后引入新元素时,由于我们要筛选出这一轮的窗口最大值,我们可以先令留在了本轮窗口的上一轮窗口的值与将要引入的值进行比对,小于就抛出,这样便维护了一个单调非递增的队列。那由于cpp中暂时没有这样的数据结构,那么我们可以利用deque自己写一个这样的队列,通过不断的循环,将每一轮的最大值加入到res数组中,最后返回。

代码如下:

class Solution {
private:
class Myqueue{
    public:   
    deque<int> que;//无论是栈或队列,底层都是由deque来实现的,它是一个双端队列
    
    void pop(int val){
    if(!que.empty() && val == que.front()){
        que.pop_front();
        }
    }
    void push(int val){
    while(!que.empty() && que.back() < val){//持续性的将小于要压入的元素的值出队
        que.pop_back();
        }
        que.push_back(val);
    }
    int get_max_val(){
        return que.front(); //由于维护的是非递增队列,队首一定是最大值
    }
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k){
    Myqueue que;
    vector<int> res;
    int len = nums.size();
    for(int i=0;i<k;i++){//先令前k个入队
        que.push(nums[i]);
    }
    res.push_back(que.get_max_val());
    for(int j=k;j<len;j++){
        que.pop(nums[j-k]);//将前一轮的首元素出队
        que.push(nums[j]);//压入新元素
        res.push_back(que.get_max_val());
    }

    return res;
  }
};

时间复杂度:O(n)
空间复杂度:O(n)

END

posted on 2025-05-24 09:19  sakura430  阅读(16)  评论(0)    收藏  举报