剑指 Offer 59 - II. 队列的最大值
题目描述
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
解答
class MaxQueue {
/**
使用单调队列解决滑动窗口的最大值问题:
本质上是一个求滑动窗口最大值的问题。这个队列可以看成是一个滑动窗口,入队就是将窗口的右边界右移,
出队就是将窗口的左边界右移。
单调队列的基本思想是:维护一个双向队列(deque),遍历序列,仅当一个元素可能成为某个区间最值时才保留它
因为滑动窗口是从前往后移动的,所以如果当后面的比前面的有可能成为最值时,因为前面的后面的先出滑动窗口,
所以前面的那个就没可能成为最值了
*/
LinkedList<Integer> ls = null;
LinkedList<Integer> maxLs = null; //linkedlist实现了双端队列接口,所以可以当作双端队列来使用
public MaxQueue() {
ls = new LinkedList<>();
maxLs = new LinkedList<>();
}
public int max_value() {
if(ls.size() == 0){
return -1;
}else{
return maxLs.peek();
}
}
public void push_back(int value) {
ls.offer(value);
while(maxLs.size() > 0&&maxLs.peekLast() < value){ //将没可能成为最值的元素从单调队列中移除,这里为最大值
maxLs.pollLast();
}
maxLs.offerLast(value); //将可能成为最值的元素放到单调队列中
}
public int pop_front() {
if(ls.size() == 0){
return -1;
}
int temp = ls.poll();
if(temp == maxLs.peekFirst()){
maxLs.pollFirst();
}
return temp;
}
}
/**
* Your MaxQueue object will be instantiated and called as such:
* MaxQueue obj = new MaxQueue();
* int param_1 = obj.max_value();
* obj.push_back(value);
* int param_3 = obj.pop_front();
*/