返回

巧用栈实现队列:LeetCode 232 解题指南

前端

用栈实现队列?初次接触这个题目,你可能和我一样,感到有些困惑。队列和栈,两种看似截然不同的数据结构,如何能够相互转换呢?

别着急,让我们一起踏上LeetCode 232 的解题之旅,探索这一巧妙的思路。

从定义理解栈和队列

在深入解决问题之前,让我们回顾一下栈和队列的基本概念:

  • 栈 (Stack): 一种后进先出 (LIFO) 的数据结构,就像一叠盘子,后放入的盘子先被取出。
  • 队列 (Queue): 一种先进先出 (FIFO) 的数据结构,就像一条排队等候的队伍,先加入队列的人员先被服务。

如何用栈实现队列

乍一看,栈和队列似乎无法相互转换,但我们可以巧妙地利用两个栈来实现队列的行为:

  1. 入队: 当我们向队列中添加一个元素时,我们将其推入 栈 A
  2. 出队: 要从队列中取出元素时,我们先将 栈 A 中的所有元素弹出并推入 栈 B。这样,栈 B 的顶部元素就是队列中的第一个元素。然后,我们从 栈 B 弹出一个元素。
  3. 窥视: 要查看队列中的第一个元素,我们只需查看 栈 A 的顶部元素。

示例代码

class MyQueue {

    private Stack<Integer> stack1;
    private Stack<Integer> stack2;

    public MyQueue() {
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }

    public void push(int x) {
        stack1.push(x);
    }

    public int pop() {
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

    public int peek() {
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.peek();
    }

    public boolean empty() {
        return stack1.isEmpty() && stack2.isEmpty();
    }
}

优势和局限

这种方法的一个主要优势是它非常高效,每个操作只需要 O(1) 的时间复杂度。然而,它的一个局限性是它需要使用额外的空间来存储元素,因为我们需要使用两个栈。

总结

通过使用两个栈,我们巧妙地实现了一个队列的数据结构,它具有后进先出的行为。这种方法为我们提供了在没有直接支持的情况下在其他语言或环境中实现队列的灵活性。

我希望这篇解题指南能帮助你深入理解这一算法。请务必尝试自己实现它,并应用到实际项目中。刷算法就像做数学题,只有通过持续的练习和深入理解,你才能真正掌握它。