一、题目
请定义一个队列并实现函数 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
二、解决
1、暴力
思路:
普通队列,遍历数组查询最大值。
代码:
class MaxQueue {
int[] q = new int[20000];
int begin = 0, end = 0;
public MaxQueue() {
}
public int max_value() {
int ans = -1;
for (int i = begin; i != end; ++i) {
ans = Math.max(ans, q[i]);
}
return ans;
}
public void push_back(int value) {
q[end++] = value;
}
public int pop_front() {
if (begin == end) {
return -1;
}
return q[begin++];
}
}
时间复杂度:
O
(
1
)
O(1)
O(1) [插入、删除],
O
(
n
)
O(n)
O(n) [求最大值]
空间复杂度:
O
(
n
)
O(n)
O(n),队列存储所有插入元素
2、单端队列
思路:
性质:当一个元素进入队列时,前面比它小的元素不再对答案产生影响。
实现:从队列尾部插入元素时,可以提取出队列中所有比这个元素小的元素,使得队列中只保留对结果有影响的数字。
==>维持队列单调递减,即保证每个元素的前面都没有比它小的元素。
过程:(可参看下图)
代码:
class MaxQueue {
private Deque<Integer> deque;
private Deque<Integer> helper;
public MaxQueue() {
deque = new ArrayDeque<>();
helper = new ArrayDeque<>();
}
public int max_value() {
//helper队头元素即为当前最大值
return deque.isEmpty() ? -1 : helper.peek();
}
public void push_back(int value) {
deque.offer(value);
//将helper队尾所有小于value的出队
while(!helper.isEmpty() && value > helper.peekLast()) {
helper.pollLast();
}
helper.offer(value);
}
public int pop_front() {
if (deque.isEmpty()) {
return -1;
}
int res = deque.poll();
//若为最大值则出队
if (helper.peek() == res) {
helper.poll();
}
return res;
}
}
时间复杂度:
O
(
1
)
O(1)
O(1) [插入、删除、求最大值]
空间复杂度:
O
(
n
)
O(n)
O(n),队列存储所有插入元素