【单调队列】LeetCode 面试题59 - II. 队列的最大值

题目链接

面试题59 - II. 队列的最大值

思路

可以看参考题解:如何解决 O(1) 复杂度的 API 设计题

一开始想到使用单变量 max 来存储最大值,但是会产生两点问题:

  • max 弹出队列之后,下一个最大值是多少没法知道
  • 如果有多个 max,那么当一个最大值弹出队列之后,队列中还有没有相同的最大值,这也没法知道

此时可以使用辅助双端队列 deque,维护 deque 中的首元素为整个队列中的最大值,第二项为次大值,以此类推。

当队列弹出元素的时候,deque 检测一下是否和首元素相等,如果相等则把首元素弹出一个。

重点说一下压入元素的部分

  • 当我们往 deque 中压入新元素并与 deque 中元素判断大小关系时一定要用小于而不是小于等于,因为最大值可能有多个。
  • 如果 deque 尾部的元素比新元素 value 小则弹出,并且不用放回。举个例子说明一下

    比如 queue=[3,2,1],此时 deque=[3,2,1],这时压入4,queue=[3,2,1,4]deque=[4][3,2,1]已经全部弹出)。

    因为4已经在 queue 的尾部了,就算再也没有元素进队列,直到 queue 变成空为止,它一直会是 queue 中的最大值,所以已经不需要前面的[3,2,1]了。

代码

class MaxQueue {
    Queue<Integer> queue;
    Deque<Integer> deque;

    public MaxQueue() {
        this.queue = new LinkedList<>();
        this.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() && deque.peekLast() < value){
            deque.removeLast();
        }

        deque.offerLast(value);
    }

    public int pop_front() {
        if(queue.isEmpty()){
            return -1;
        }

        int num = queue.poll();
        if(deque.peekFirst().equals(num)){
            deque.pollFirst();
        }

        return num;
    }
}
posted @ 2023-03-28 20:02  Frodo1124  阅读(25)  评论(0编辑  收藏  举报