【剑指offer】59 - II. 队列的最大值

剑指 Offer 59 - II. 队列的最大值

知识点:队列;单调

题目描述

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

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

示例
输入: 
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
输出: [null,null,null,2,1,2]

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

解法一:双端队列+单调

当一个元素进入队列时,它前面所有比它小的元素就不会再对答案产生影响了

比如数字序列 1 1 1 1 2,那么在第一个数字 2 被插入后,数字 2 前面的所有数字 1 将不会对结果产生影响。因为如果数字 1 在队列中,那么数字 2 必然也在队列中(先进先出),使得数字 1 对结果没有影响。

所以当从队列尾部插入元素时,可以把没有影响的,也就是所有比要插入元素小的数字都取出来,使得队列中只保留对结果有影响的数字,也就是要求队列单调递减;

在元素入队时,判断当前元素和队尾的关系,把所有小于当前值的队里元素都移除;

所以可以在添加和删除的时候采用普通的队列;
在取出最大值的时候采用双端队列;双端队列维持递减,所以每次取出队首元素即可;

class MaxQueue {
    Queue<Integer> queue;
    Deque<Integer> deque;
    public MaxQueue() {
        queue = new LinkedList<>();
        deque = new LinkedList<>();
    }
    
    public int max_value() {
        if(deque.isEmpty()) return -1;
        return deque.peekFirst();
    }
    
    public void push_back(int value) {
        queue.offer(value);
        while(!deque.isEmpty() && value > deque.peekLast()){
            deque.removeLast();  //维持一个单调递减队列;
        }
        deque.offerLast(value);
    }
    
    public int pop_front() {
        if(queue.isEmpty()) return -1;
        int ans = queue.poll();
        if(ans == deque.peekFirst()){
            deque.removeFirst();
        }
        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();
 */
posted @ 2021-08-11 21:58  Curryxin  阅读(51)  评论(0编辑  收藏  举报
Live2D