Bootstrap

【LeetCode刷题(中等程度)】剑指 Offer 59 - II. 队列的最大值

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

若队列为空,pop_front 和 max_value 需要返回 -1

示例 1:

输入:
[“MaxQueue”,“push_back”,“push_back”,“max_value”,“pop_front”,“max_value”]
[[],[1],[2],[],[],[]]
输出: [null,null,null,2,1,2]

示例 2:

输入:
[“MaxQueue”,“pop_front”,“max_value”]
[[],[],[]]
输出: [null,-1,-1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:本题可以参考前一题的思路剑指 Offer 59 - I. 滑动窗口的最大值,我们可以维护一个最大值队列。最大值队列中队头元素最大,队尾元素最小。并且依次记录入data队尾的数据的顺序。我们需要确定的两个点是:

  1. 什么时候更新队尾?(如果当前入队的值大于队尾的值,那么就更新最大值队列队尾值)
  2. 什么时候出队头?(如果data队列当前弹出的元素的位置刚好是最大值队列max队头对应的位置,那么我们就需要将max队头出队,因为当前的最大值已经被弹出去了)。

代码实现:

class MaxQueue {
public:
    MaxQueue() {
        curIndex = 0;
    }
    
    int max_value() {
        if(_max.empty())
            return -1;
        return _max.front().number;
    }
    
    void push_back(int value) {
        //考虑什么时候出队尾 当新进来的值大于等于队尾
        while(!_max.empty() && value >= _max.back().number)
            _max.pop_back();
        Inernal_Data temp_data = {value,curIndex};
        
        _max.push_back(temp_data);
        _data.push_back(temp_data);

        ++curIndex;//维护数据的顺序
    }
    
    int pop_front() {
        if(_max.empty())
            return -1;
        //若当前弹出的元素刚好是 窗口中最大元素 更新_max队列中内容
        if(_data.front().index == _max.front().index)
            _max.pop_front();
        
        int res = _data.front().number;
        _data.pop_front();
        return res;
    }
private:

    struct Inernal_Data
    {
        int number;
        int index;
    };
    deque<Inernal_Data> _data;
    deque<Inernal_Data> _max;
    int curIndex;
};

/**
 * 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();
 */

关于插入时间复杂度分析:
对于最大值队列_max,每个数据最多只能入队一次,那么也可能最多出队一次,考虑n个数据,那么总共最多出队次数也只有n次,平均下来单次插入也只有O(1)时间复杂度。

;