每日一题 - 剑指 Offer 59 - II. 队列的最大值
Posted id-wangqiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一题 - 剑指 Offer 59 - II. 队列的最大值相关的知识,希望对你有一定的参考价值。
题目信息
-
时间: 2019-07-05
-
题目链接:Leetcode
-
tag: 队列 双端队列
-
难易程度:中等
-
题目描述:
请定义一个队列并实现函数 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. 1 <= push_back,pop_front,max_value的总操作数 <= 10000
2. 1 <= value <= 10^5
解题思路
本题难点
时间复杂度有要求为O(N)
具体思路
使用两个队列:一个队列正常入队出队;再用一个双端队列来辅助作为单调队列,维护队头最大值。这样max_value()查询,单调队列队首的值就是查询的最大值。
代码
class MaxQueue {
Queue<Integer> queue;
Deque<Integer> deque;
public MaxQueue() {
queue = new LinkedList<>();
deque = new LinkedList<>();
}
public int max_value() {
//单调队列队首就是最大值
return queue.isEmpty() ? -1 : deque.peekFirst();
}
public void push_back(int value) {
queue.add(value);
//维护单调队列的单调性:把小的都出队了 队列剩余的都是比当前元素大的,所以是单调递增,队首就是最大值
//如果之前入队的队尾比后入队的当前元素还要小,就让队尾出队
while(!deque.isEmpty() && deque.peekLast() < value){
deque.pollLast();
}
deque.add(value);
}
public int pop_front() {
//当普通队列的队首元素 等于 单调队列队首 就让单调队列队首出队
if(!deque.isEmpty() && deque.peekFirst().equals(queue.peek())){
deque.pollFirst();
}
return queue.isEmpty() ? -1 : queue.poll();
}
}
复杂度分析:
- 时间复杂度 O(1) : 删除操作于求最大值操作显然只需要 O(1) 的时间。而插入操作虽然看起来有循环,做一个插入操作时最多可能会有 n 次出队操作。但要注意,由于每个数字只会出队一次,因此对于所有的 n 个数字的插入过程,对应的所有出队操作也不会大于 n 次。因此将出队的时间均摊到每个插入操作上,时间复杂度为 O(1)。
- 空间复杂度 O(N) : 需要用队列存储所有插入的元素。
以上是关于每日一题 - 剑指 Offer 59 - II. 队列的最大值的主要内容,如果未能解决你的问题,请参考以下文章
Java每日一题——>剑指 Offer II 027. 回文链表
Java每日一题——>剑指 Offer II 029. 排序的循环链表