“Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。”
一、题目描述: 请定义一个队列并实现函数 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
二、思路分析:
使用一个辅助队列maxq,我们希望当要获取最大值时,返回maxq的首位,当我们排出首位时当首位不是最大值时没影响,但当首位是最大值值时我们希望原maxq的第二位就是原对象的第二大的值。那么如何实现呢?
如果我们只把大于maxq的值插入,那么面对 9 1 1时删除首位不能得到新的最大值1,而面对9 1 1 10时却能符合要求,这是因为10在1后面,1对maxq影响已经没有了,故10加入时因排出所有小于10的数
因为队列queue是先进先出的,当出现第二大时可能与最大值相隔很多的比他小的值,而这些小值先于第二大值排出且对最大值顺序没影响,故我们把maxq中小于第大二的值全部排出再加入;而最大值先排出,这样第二大值顺位推进。
故辅助队列maxq中按降序排列,插入新值时从maxq队列尾部依次取出比当前元素小的元素,直到遇到一个比当前元素大的元素。这样前面的无关的小值不会影响
- max_value,为空返回-1,否则返回首位
- push_back 为空两个队列都加入,否则maxq队列尾部依次取出比当前元素小的元素再加入
- pop_front 为空返回-1,否则判断删除的是否为最大值,是删除首位,否不做操作
三、AC代码
var MaxQueue = function() {
this.maxq=[];
this.queue=[];
};
/**
* @return {number}
*/
MaxQueue.prototype.max_value = function() {
let maxq=this.maxq;
if(maxq.length){
return maxq[0]
}else return -1
};
/**
* @param {number} value
* @return {void}
*/
MaxQueue.prototype.push_back = function(value) {
let [maxq,queue]=[this.maxq,this.queue];
while(maxq.length&&maxq[maxq.length-1]<value)maxq.pop()
maxq.push(value);
queue.push(value);
};
/**
* @return {number}
*/
MaxQueue.prototype.pop_front = function() {
let [maxq,queue]=[this.maxq,this.queue];
if(queue.length){
let value=queue.shift();
if(value===maxq[0])maxq.shift()
return value;
}else return -1;
};
/**
* Your MaxQueue object will be instantiated and called as such:
* var obj = new MaxQueue()
* var param_1 = obj.max_value()
* obj.push_back(value)
* var param_3 = obj.pop_front()
*/
四、总结
本题和请定义一个最大栈大同小异,都是借助了对应的辅助数据结构。对最大栈来说,因为栈先进后出,其辅助栈只需加入比原先大的值即可;对最大队列来说,因为队列先进先出,辅助栈加入时要把比新值小的数全部排出。