剑指 Offer 59-I/59-II 滑动窗口的最大值/队列的最大值C++

59-I

题目描述

在这里插入图片描述

解法 双端队列

维护一个back到front不断增大的双端队列,队首为滑动窗口的最大值,当窗口移动一位时,有以下两个动作。

  1. 进入新的元素,从队尾开始,不断将小于他的元素pop,直到找到大于它的元素再将其压入队尾。
    这不难理解,新进入的数字大于队内的数字,说明队内的数字是绝对没有意义的,不可能成为最大值,并且出去的时刻肯定比新数字早
  2. 弹出旧的元素,只需要判断队首的元素和弹出的元素是否相同,相同则弹出。
    可能就会问,那队首被弹出之后,新的元素又不是移动窗口的最大元素,怎么知道移动窗口的最大元素还在队首呢。我们假设最大元素此时在队首,后面又进入了比它更小的元素,如果这个元素有作为下一个窗口的最大值的潜质,一定会被保存在队首的下一位,这时候队首出队它就是最大元素了
    总结来说就是遇到新的数字时,之前的小数字就直接抛弃,新的数字先放进去再说。
class Solution {
    
    
public:
    void popNum(deque<int>& que, int value) {
    
    
        if(!que.empty() && que.front() == value) que.pop_front();
    }
    void pushNum(deque<int>& que,int value) {
    
    
        while(!que.empty() && que.back() < value) que.pop_back();
        que.push_back(value);
    }
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    
    
        if(nums.size()==0) return {
    
    };
        deque <int> que; 
        vector<int> ans;
        //先将处理前k个元素
        for(int i = 0; i < k; i ++) {
    
    
            pushNum(que, nums[i]);
        }
        //前k个元素的最大值
        ans.push_back(que.front());
        for(int i = k; i < nums.size(); i++) {
    
    
            pushNum(que, nums[i]);
            popNum(que, nums[i - k]);
            ans.push_back(que.front());
        }
        return ans;

    }
};


时间复杂度O(N),每个元素最多被pop push各一次
空间复杂度O(K)

59-II

题目描述

在这里插入图片描述

解法 辅助双端队列

沿袭刚才的思路,建立一个维护最大值的辅助双端队列即可,然后再建立一个一般的队列用于pop和push,pop的时候判断一下双端队列的队首是不是被pop了

class MaxQueue {
    
    
public:
    //获取最大值用的
    deque<int> que;
    //存储数字
    queue<int> q;
    MaxQueue() {
    
    
    }
    
    int max_value() {
    
    
        if(que.empty()) return -1;
        return this -> que.front();
    }
    
    void push_back(int value) {
    
    
        while(!this -> que.empty() && value > this -> que.back()) this -> que.pop_back();
        this -> que.push_back(value);
        this -> q.push(value);
    }
    
    int pop_front() {
    
    
        if(q.empty()) return -1;
        if(q.front() == que.front()) que.pop_front();
        int ans = q.front();
        q.pop();
        return ans;
    }
};

/**
 * Your MaxQueue object will be instantiated and called as such:
 * MaxQueue* obj = new MaxQueue();
 * int param_1 = obj->max_value();
 * obj->push_back(value);
 * int param_3 = obj->pop_front();
 */

在这里插入图片描述

时间复杂度O(1)
空间复杂度O(N)

猜你喜欢

转载自blog.csdn.net/qq_42883222/article/details/112646094