[路飞]leetcode 1670. 设计前中后队列

110 阅读2分钟

请你设计一个队列,支持在前,中,后三个位置的 push 和 pop 操作。原文链接

请你完成 FrontMiddleBack 类:

FrontMiddleBack() 初始化队列。
void pushFront(int val) 将 val 添加到队列的 最前面 。
void pushMiddle(int val) 将 val 添加到队列的 正中间 。
void pushBack(int val) 将 val 添加到队里的 最后面 。
int popFront() 将 最前面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。
int popMiddle() 将 正中间 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。
int popBack() 将 最后面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。

请注意当有 两个 中间位置的时候,选择靠前面的位置进行操作。比方说: 将 6 添加到 [1, 2, 3, 4, 5] 的中间位置,结果数组为 [1, 2, 6, 3, 4, 5] 。 从 [1, 2, 3, 4, 5, 6] 的中间位置弹出元素,返回 3 ,数组变为 [1, 2, 4, 5, 6] 。

大体有两种方式
第一种是利用数组的特性实现unshift、push、shift、pop、splice
第二种是链表实现emptynode.next=emptynode.next.next,last-1Node.next=null,node[mikey-].next=node[mikey].next.next

不管第一种还是第二种对Middle的操作都是需要找到中间元素,可以用size>>1,和(size-1)>>1

实现2 -> 利用数组的特性


var FrontMiddleBackQueue = function () {
  this.list = [];
};

/**
 * @param {number} val
 * @return {void}
 */
FrontMiddleBackQueue.prototype.pushFront = function (val) {
  this.list.unshift(val);
};

/**
 * @param {number} val
 * @return {void}
 */
FrontMiddleBackQueue.prototype.pushMiddle = function (val) {
  var mid = this.list.length >> 1;
  this.list.splice(mid, 0, val);
};

/**
 * @param {number} val
 * @return {void}
 */
FrontMiddleBackQueue.prototype.pushBack = function (val) {
  this.list.push(val);
};

/**
 * @return {number}
 */
FrontMiddleBackQueue.prototype.popFront = function () {
  if (this.isEmpty()) return -1;
  return this.list.shift();
};

/**
 * @return {number}
 */
FrontMiddleBackQueue.prototype.popMiddle = function () {
  if (this.isEmpty()) return -1;
  var mid = (this.list.length - 1) >> 1;
  let item = this.list.splice(mid, 1);
  return item[0];
};

/**
 * @return {number}
 */
FrontMiddleBackQueue.prototype.popBack = function () {
  if (this.isEmpty()) return -1;
  return this.list.pop();
};
FrontMiddleBackQueue.prototype.getMiddlekey = function () {
  return parseInt(this.list.length / 2);
};
FrontMiddleBackQueue.prototype.isEmpty = function () {
  return this.list.length === 0;
};

实现2 -> 利用链表


function Node(val, next) {
  this.val = val != undefined ? val : null;
  this.next = next != undefined ? next : null;
}

class FrontMiddleBackQueue{
  constructor() {
    this.list = new Node(-1);
    this.size = 0;
  }
  toArray() {
    let array = [];
    let cur = this.list.next;
    while (cur) {
      array.push(cur.val);
      cur = cur.next;
    }
    console.log(array);
  }
  pushFront(val) {
    this.list.next = new Node(val, this.list.next);
    this.size++;
  }
  pushMiddle(val) {
    let midKey = this.size >> 1;
    let cur = this.list;
    while (midKey > 0) {
      midKey--;
      cur = cur.next;
    }
    this.size++;
    cur.next = new Node(val, cur.next);
  }
  pushBack(val) {
    this.getEndNode().next = new Node(val);
    this.size++;
  }
  popFront() {
    if (this.isEmpty()) return -1;
    let head = this.list;
    let val=head.next.val
    this.list.next = this.list.next.next;
    this.size--;
    return val;
  }
  popMiddle() {
    if(this.isEmpty())return -1
  
    let midKey=(this.size-1)>>1
   let cur=this.list
   while(midKey>0){
    cur=cur.next
    midKey--
   }
  
   let val=cur.next.val
   cur.next=cur.next.next
   this.size--
   return val

  }
  popBack() {
    if (this.isEmpty()) return -1;
    let cur = this.list;
    while (cur && cur.next && cur.next.next) {
      cur = cur.next;
    }
    let val = cur.next.val;
    cur.next = null;
    this.size--;
    return val;
  }
  isEmpty() {
    return this.size === 0;
  }
  getEndNode() {
    let cur = this.list;
    while (cur && cur.next) {
      cur = cur.next;
    }
    return cur;
  }
}