题目
算法思路
“空间换时间”,构建一个递减列表来保存队列内元素,使得队列最大元素始终位于列表首位,显然需要使用 双向队列。
当执行入队操作时:若队列内存在小于该元素
x
x
x 的数字,则应将 双向队列尾部 所有小于
x
x
x 的元素弹出;
当执行出队操作时:若出队的元素时队列内的最大元素,则应将 双向队列首元素 出队,保持其与队列内元素的一致性。
具体函数设计:
获取最大值max_value()
:
- 若
deque
为空,返回 -1; - 否则返回
deque
首元素。
入队push_back()
:
- 将元素
x
x
x 压入
queue
; - 将
deque
中所有 小于 x x x 的元素弹出,然后将 x x x 压入。
出队pop_front()
:
- 若
queue
为空,返回 -1; - 否则将
queue
首元素弹出; - 若
deque
首元素等于queue
首元素,则deque
的首元素也要弹出(因为入队操作中小于 x x x 的会弹出deque
,所以当出队的元素不是当前队列中的最大元素时,该元素已经不在deque
内了)。
具体代码
class MaxQueue {
Queue<Integer> queue;
Deque<Integer> deque;
public MaxQueue() {
queue = new LinkedList<>();
deque = new LinkedList<>();
}
public int max_value() {
return deque.isEmpty() ? -1 : deque.peekFirst();
}
public void push_back(int value) {
queue.offer(value);
while(!deque.isEmpty() && deque.peekLast() < value){
deque.pollLast();
}
deque.offerLast(value);
}
public int pop_front() {
if(queue.isEmpty())return -1;
if(queue.peek().equals(deque.peekFirst())){
deque.pollFirst();
}
return queue.poll();
}
}
/**
* 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();
*/
注意:比较queue
和deque
的首元素大小时要用equals()
而不能用==
,因为queue.peek()
中保存的是Integer类型,没有自动拆箱。
复杂度分析
- 时间复杂度:三个函数的均摊时间复杂度均为 O ( 1 ) O(1) O(1),注意,每个元素最多压入、弹出各一次,最多 2n 次操作。
- 空间复杂度:
O
(
n
)
O(n)
O(n),最坏情况下
deque
会保存 n 个元素。