请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front的时间复杂度都是O(1)。若队列为空,pop_front 和 max_value 需要返回 -1。
输入:
["MaxQueue","push_back","push_back",
"max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
输出:
[null,null,null,2,1,2]
输入:
["MaxQueue","pop_front","max_value"]
[[],[],[]]
输出:
[null,-1,-1]
题目讲解
解法1:常规解法
【核心思想】
- 用两个队列来完成任务
【数据结构】
- 队列与双向队列
【思路】
- 用一个队列保存正常元素,另一个双向队列保存单调递减的元素
- 入栈时,第一个队列正常入栈;第二个队列是递减队列,所以需要与之前的比较,从尾部把小于当前value的全部删除(因为用不到了)
- 出栈时,第一个队列正常出栈;第二个队列的头部与出栈的值作比较,如果相同,那么一起出栈
【代码】
public class MaxQueue {
Queue<Integer> queue;
Deque<Integer> maxQueue;
public MaxQueue() {
queue=new ArrayDeque();
maxQueue=new ArrayDeque();
}
public int max_value() {
if(maxQueue.isEmpty())
return -1;
return maxQueue.peek();
}
public void push_back(int value) {
queue.add(value);
while(!maxQueue.isEmpty() && value>maxQueue.getLast())
maxQueue.pollLast();
maxQueue.add(value);
}
public int pop_front() {
if(queue.isEmpty())
return -1;
int ans=queue.poll();
if(ans==maxQueue.peek())
maxQueue.poll();
return ans;
}
}
【备注】
- 存储单调递减的元素的队列需要是双向队列
- 如果面试官不允许用STL怎么办呢?自己手撸两个队列,解法如下。
解法2:提升解法
【数据结构】
- 数组
【思路】
- 使用head和tail标志,用两个数组模拟队列
- 由题目的限制条件选择数组长度
【代码】
public class MaxQueue {
int[] queue;
int queueHead;
int queueTail;
int[] maxQueue;
int maxQueueHead;
int maxQueueTail;
public MaxQueue() {
queue=new int[20005];
queueHead=0;
queueTail=0;
maxQueue=new int[20005];
maxQueueHead=0;
maxQueueTail=0;
}
public int max_value() {
if(maxQueueTail==maxQueueHead)
return -1;
return maxQueue[maxQueueHead];
}
public void push_back(int value) {
if(queueTail>=20000)
throw new OutOfMemoryError();
queue[queueTail++]=value;
while(maxQueueHead!=maxQueueTail && value>maxQueue[maxQueueTail-1])//注意这边是从尾部开始比较的
maxQueueTail--;
maxQueue[maxQueueTail++]=value;
}
public int pop_front() {
if(queueHead==queueTail)
return -1;
int ans=queue[queueHead];
if(ans==maxQueue[maxQueueHead])
maxQueueHead++;
queueHead++;
return ans;
}
}
关注微信公众号“算法岗从零到无穷”,更多算法知识点告诉你。