LeetCode-剑指 Offer 59 - II. 队列的最大值

63 阅读1分钟

题目

请定义一个队列并实现函数 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

思路

用两个对象模拟队列,因为时间复杂度都是O(1),所以不使用遍历的方式,就有了如下思路:

  1. 一个队列queue存储所有数据,另一个队列deque维护每个阶段的最大值,就变成一个递减的队列,到时候最大值就是队首值,这样时间复杂度为O(1),所以这个队列是一个双端队列
  2. 队尾入队:当要添加的数据比双端队列队尾值小时,直接入双端队列deque;如果要添加的数据比双端队列队尾值大时,用这个值“代替”队尾值,即把当前队尾值删掉,把这个要添加的数据入队,以此类推;
  3. 队首出队:比较queue和deque的队首值,如果相同,双端队列deque出队,否则deque不操作,按照题目要求,当queue为空时,返回-1;
  4. 获取队列最大值:按照题目要求,当deque为空时,返回-1,否则直接获取队首值即为最大值。

代码

var MaxQueue = function() {
  // 存储队列数据
  this.queue = {}
  // 双端队列维护最大值(每个阶段的最大值)
  this.deque = {}
  // head队首 count队尾
  this.headQ = this.headD = this.countQ = this.countD = 0
};

/** 队尾入队
 * @param {number} value
 * @return {void}
 */
MaxQueue.prototype.push_back = function(value) {
  // 数据在queue入队
  this.queue[this.countQ++] = value
  // 检测是否可以将数据添加到双端队列
  while(!this.isEmptyDeque() && value > this.deque[this.countD-1]){
    delete this.deque[--this.countD]
  }
  // 要添加的数据比双端队列队尾值小,入队
  this.deque[this.countD++] = value
};

/**队首出队
 * @return {number}
 */
 MaxQueue.prototype.pop_front = function() {
  if(this.isEmptyQueue()){
    // 题目要求
    return -1
  }
  // 比较queue和deque的队首值,如果相同,双端队列deque出队,否则deque不操作
  if(this.queue[this.headQ] === this.deque[this.headD]){
    delete this.deque[this.headD]
    this.headD++
  }
  // 获取到queue出队的值,并返回
  const frontData = this.queue[this.headQ]
  delete this.queue[this.headQ]
  this.headQ++
  return frontData
};

/**获取队列最大值
 * @return {number}
 */
MaxQueue.prototype.max_value = function() {
  if(this.isEmptyDeque()){
    // 题目要求
    return -1
  }
  return this.deque[this.headD]
};

MaxQueue.prototype.isEmptyQueue = function(){
  return this.countQ - this.headQ === 0
}

MaxQueue.prototype.isEmptyDeque = function(){
  return this.countD - this.headD === 0
}

image.png