剑指 Offer 59 - II. 队列的最大值
题目
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
思路
这题也是用单调队列来解决,参考链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/mian-shi-ti-59-ii-dui-lie-de-zui-da-zhi-by-leetcod/
本算法基于问题的一个重要性质:当一个元素进入队列的时候,它前面所有比它小的元素就不会再对答案产生影响。
上面的性质是非常关键的。举个例子,如果我们向队列中插入数字序列 1 1 1 1 2,那么在第一个数字 2 被插入后,数字 2 前面的所有数字 1 将不会对结果产生影响。因为按照队列的取出顺序,数字 2 只能在所有的数字 1 被取出之后才能被取出,因此如果数字 1 如果在队列中,那么数字 2 必然也在队列中,使得数字 1 对结果没有影响。
这样的话,如果当前队列中元素是1 1 1 2,那么此时我们要从队列中弹出1,那么根据队列先进先出的原则,1可以直接弹出,因为1不是最大值,不会对弹出后队列的最大值造成影响,所以直接弹出就行了。如果要是弹出2,因为队列最大值是2,那么就要在单调数组中把2删除
代码
class MaxQueue {
ArrayDeque<Integer> A = new ArrayDeque<>(); //用于存储队列中的最大值,是个单调不增队列
ArrayList<Integer> L =new ArrayList(); //用于存储队列中的数据
int head = 0; //指示队列的头
int size =0; //指示队列的尾。
//其实,这里存储队列中的数据,可以用一个ArrayDeque来实现,就不需要head这个头指针了
//构造函数
public MaxQueue() {
A = new ArrayDeque<>();
L =new ArrayList();
}
// 返回单调队列A中的第一个元素就行了
public int max_value() {
if(size==0){
return -1;
}
return A.peekFirst();
}
// 队列中加元素
public void push_back(int value) {
L.add(value); //首先将数据放入数组L中,然后将size++
size++;
// 对单调队列A中的最后的元素进行判断,删除比value小的元素
while(!A.isEmpty() && A.peekLast()<value){
A.pollLast();
}
A.addLast(value); //将value加入
}
//队列中弹出元素
public int pop_front() {
if(size==0){
return -1;
}
if(L.get(head)<max_value()){
}else{
A.pollFirst(); //因为弹出的是最大值,所以需要把单调队列A中的第一个元素删除
}
size--;
return L.get(head++);
}
}