返回

利用JavaScript妙手回春:用栈构建队列,搞定剑指 Offer JavaScript刷题第 1 天挑战!

前端

站在剑指 Offer JavaScript刷题的起跑线上,我们面临的第一道难题便是用两个栈实现队列。栈和队列都是计算机科学中常见的数据结构,栈遵循先进后出的原则,而队列遵循先进先出的原则。乍一看,栈似乎与队列格格不入,但通过巧妙的设计,我们可以用两个栈模拟出一个队列。

栈与队列的数据结构

1. 栈

栈是一种遵循先进后出(LIFO)原则的数据结构,类似于生活中的一叠盘子。当我们把盘子叠起来时,最后放上的盘子会先被取走,这就是先进后出的原则。在栈中,我们可以通过push()方法添加元素,通过pop()方法移除元素,同时也可以通过peek()方法查看栈顶元素。

2. 队列

队列是一种遵循先进先出(FIFO)原则的数据结构,就像生活中排队等候一样。队列中的第一个元素会先被处理,这就是先进先出的原则。在队列中,我们可以通过enqueue()方法添加元素,通过dequeue()方法移除元素,同时也可以通过peek()方法查看队列头元素。

用两个栈实现队列

既然栈是先进后出,队列是先进先出,那么如何用两个栈模拟出一个队列呢?秘诀在于巧妙地利用栈的特性。

  1. 入队操作 :当我们需要将一个元素入队时,我们先将其压入栈A。
  2. 出队操作 :当我们需要将一个元素出队时,我们先将栈A中的所有元素依次压入栈B,然后将栈B中的栈顶元素弹出,这就是出队的元素。

通过这种方法,我们可以用两个栈模拟出一个队列,并且队列的基本操作enqueue()、dequeue()和peek()的时间复杂度都是O(1)。

代码实现

class Queue {
  constructor() {
    this.stackA = [];
    this.stackB = [];
  }

  enqueue(element) {
    this.stackA.push(element);
  }

  dequeue() {
    if (this.stackB.length === 0) {
      while (this.stackA.length > 0) {
        this.stackB.push(this.stackA.pop());
      }
    }
    return this.stackB.pop();
  }

  peek() {
    if (this.stackB.length === 0) {
      while (this.stackA.length > 0) {
        this.stackB.push(this.stackA.pop());
      }
    }
    return this.stackB[this.stackB.length - 1];
  }
}

结语

通过用两个栈实现队列的挑战,我们不仅加深了对栈和队列数据结构的理解,也领略了算法设计中的巧思。剑指 Offer JavaScript刷题之旅才刚刚开始,在接下来的日子里,我们将继续探索更多精彩的算法和数据结构,不断磨炼我们的编程技能。