【单调队列】LeetCode 面试题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;
}
}