JZ59 队列的最大值

60 阅读1分钟

leetcode.cn/problems/du…

请定义一个队列并实现函数 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]  

限制:

1 <= push_back,pop_front,max_value的总操作数 <= 10000 1 <= value <= 10^5

解题思路

image.png

image.png

考虑利用 数据结构 来实现,即经常使用的 “空间换时间” 。如下图所示,考虑构建一个递减列表来保存队列 所有递减的元素 ,递减链表随着入队和出队操作实时更新,这样队列最大元素就始终对应递减列表的首元素,实现了获取最大值 O(1) 时间复杂度。

image.png

image.png

设计双向队列为 单调不增 的原因:若队列 queue 中存在两个 值相同的最大元素 ,此时 queue 和 deque 同时弹出一个最大元素,而 queue 中还有一个此最大元素;即采用单调递减将导致两队列中的元素不一致。

复杂度分析:

时间复杂度 O(1) : max_value(), push_back(), pop_front() 方法的均摊时间复杂度均为 O(1);

空间复杂度 O(N) : 当元素个数为 N 时,最差情况下deque 中保存 N 个元素,使用 O(N) 的额外空间;

代码:

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;
        } else {
            return deque.getFirst();
        }
    }

    public void push_back(int value) {
        queue.offer(value);
        if (deque.isEmpty()) {
            deque.addFirst(value);
        } else {
            deque.removeIf(integer -> integer < value);
            deque.addLast(value);
        }
    }

    public int pop_front() {
        if (queue.isEmpty()) {
            return -1;
        } else {
            if (queue.peek().equals(deque.getFirst())) {
                deque.removeFirst();
            }
            return queue.poll();
        }
    }
}