Medium | 剑指 Offer 59 - II. 队列的最大值 | 设计
剑指 Offer 59 - II. 队列的最大值
请定义一个队列并实现函数 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
解体思路
此题与Hard | LeetCode 239 | 剑指 Offer 59 - I. 滑动窗口的最大值 是一样的, 区别在于前一道题是窗口的大小限制让元素不得不出队, 而这道题他是随时都可以出队, 也随时可以不出队。所以解法都是一样, 使用一个辅助的单调递减队列记录可能成为最大值的元素。不过这里就不能存下标了, 直接存值。如果出队的元素恰好是单调队列的队首元素, 那么单调队列队首元素也必须出队。
class MaxQueue {
// 用于存储所有数据队列
private Deque<Integer> queue;
// 单调递减队列, 用以存储可能成为队列最大值的元素
private Deque<Integer> monotonicQueue;
public MaxQueue() {
queue = new ArrayDeque<>();
monotonicQueue = new ArrayDeque<>();
}
// 需要实现的方法 获取队列里的最大值
public int max_value() {
if (!monotonicQueue.isEmpty()) {
return monotonicQueue.peek();
}
return -1;
}
// 需要实现的方法 队列入队元素
public void push_back(int value) {
queue.add(value);
while (!monotonicQueue.isEmpty()) {
int val = monotonicQueue.getLast();
if (value > val) {
monotonicQueue.removeLast();
} else {
break;
}
}
monotonicQueue.add(value);
}
// 需要实现的方法 队首元素出队
public int pop_front() {
if (!queue.isEmpty()) {
int head = queue.poll();
if (head == monotonicQueue.peek()) {
monotonicQueue.poll();
}
return head;
}
return -1;
}
}