学算法刷LeetCode【剑指offer专题】:59-II.队列的最大值

298 阅读1分钟

题目描述

image.png

59-II.队列的最大值

解题思路

思路1(暴力解法)

使用队列的特性尾部插入,头部删除实现 push_back 和 pop_front, 至于寻找最大值,则遍历队列元素,找到最大值就返回,否则返回 -1。

时间复杂度:max_value 为O(n), 其余为 O(1) 空间复杂度: O(n)

代码略

思路2(维护一个单调的双端队列)

我们从上面分析得知,实际上最耗时的是找到最大值,那么我们可以针对这个寻找过程做一些优化,增加一个队列,这个队列里面存放最大值。

  • push_back 元素时, 普通的队列(队列1)直接在队尾添加元素,而单调队列则需要判断一下,如果队列的头部元素比当前元素都要小,将整个队列的元素出队,再将当前元素添加到队尾
  • max_value 时,如果队列2不为空,则它的队首元素为最大值,否则,没有最大值,返回 -1.

代码

JS

var MaxQueue = function() {
    this.queue1 = [];
    this.queue2 = [];
}

MaxQueue.prototype.push_back = function(value){
    // 单调队列里的最大值比当前值小,则清空整个队列。
    while(this.queue2.length && this.queue2[this.queue2.length - 1] < value){
        this.queue2.pop();
    }
    this.queue1.push(value);
    this.queue2.push(value);
}

MaxQueue.prototype.pop_front = function(){
    // 队列为空,返回 -1
    if(!this.queue1.length) return -1;
    
    // 元素存在,返回队头删除的元素
    const val = this.queue1.shift();
    if(this.queue2.length && this.queue2[0] === val){
        this.queue2.shift();
    }
    return val;
}

MaxQueue.prototype.max_value = function(){
    return this.queue2.length ? this.queue2[0] : -1

}

总结

关键思路在于如何优化的取得最大值的时间复杂度(max_value), 利用单调队列,维护最大值即可,同时记得删除队首元素的时候,判断一下该元素是否正好也在单调队列中即可。

时间复杂度: O(1)

空间复杂度: O(n)