用栈实现队列
In this problem, we are required to implement a queue using two stacks. The queue should support all four standard operations: push
, pop
, peek
, and empty
.
在这个问题中,我们需要使用两个栈来实现一个队列。该队列应支持所有四种标准操作:push
、pop
、peek
和 empty
。
Approach
The key idea to implement a queue using two stacks is to use one stack (stack1
) to handle incoming elements (push operations) and another stack (stack2
) to handle outgoing elements (pop and peek operations). The approach works as follows:
使用两个栈实现队列的关键思路是使用一个栈(stack1
)处理传入的元素(push 操作),另一个栈(stack2
)处理传出的元素(pop 和 peek 操作)。该方法的工作原理如下:
-
Push Operation:
- Always push the new element into
stack1
.
Push 操作:
- 始终将新元素推入
stack1
。
- Always push the new element into
-
Pop Operation:
- If
stack2
is empty, transfer all elements fromstack1
tostack2
. Then, pop the top element fromstack2
.
Pop 操作:
- 如果
stack2
为空,将stack1
中的所有元素转移到stack2
中。然后,从stack2
中弹出顶部元素。
- If
-
Peek Operation:
- If
stack2
is empty, transfer all elements fromstack1
tostack2
. Then, return the top element fromstack2
.
Peek 操作:
- 如果
stack2
为空,将stack1
中的所有元素转移到stack2
中。然后,从stack2
中返回顶部元素。
- If
-
Empty Operation:
- The queue is empty if both
stack1
andstack2
are empty.
Empty 操作:
- 如果
stack1
和stack2
都为空,则队列为空。
- The queue is empty if both
Example Implementation
Here is how the MyQueue
class can be implemented:
下面是 MyQueue
类的实现:
class MyQueue:
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, x: int) -> None:
self.stack1.append(x)
def pop(self) -> int:
self.peek()
return self.stack2.pop()
def peek(self) -> int:
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2[-1]
def empty(self) -> bool:
return not self.stack1 and not self.stack2
Explanation
-
Initialization: Two stacks are initialized:
stack1
andstack2
.初始化:初始化了两个栈:
stack1
和stack2
。 -
Push Operation: The
push
method appends the element tostack1
.Push 操作:
push
方法将元素追加到stack1
中。 -
Pop Operation: The
pop
method ensures thatstack2
is populated by transferring elements fromstack1
, then pops the top element fromstack2
.Pop 操作:
pop
方法确保stack2
被填充,通过将元素从stack1
转移到stack2
,然后从stack2
弹出顶部元素。 -
Peek Operation: The
peek
method checks ifstack2
is empty and, if so, transfers elements fromstack1
tostack2
, then returns the top element ofstack2
.Peek 操作:
peek
方法检查stack2
是否为空,如果为空,则将元素从stack1
转移到stack2
,然后返回stack2
的顶部元素。 -
Empty Operation: The
empty
method checks if both stacks are empty.Empty 操作:
empty
方法检查两个栈是否都为空。
Time Complexity
- Push Operation: O(1)
- Pop Operation: Amortized O(1)
- Peek Operation: Amortized O(1)
- Empty Operation: O(1)
时间复杂度
- Push 操作:O(1)
- Pop 操作:均摊 O(1)
- Peek 操作:均摊 O(1)
- Empty 操作:O(1)
Interview Questions
-
Why do we need two stacks to implement a queue?
- Two stacks are required to reverse the order of elements so that we can achieve FIFO behavior using LIFO stacks.
为什么需要两个栈来实现队列?
- 需要两个栈来反转元素的顺序,以便我们可以使用 LIFO 栈实现 FIFO 行为。
-
What is the time complexity of the pop operation?
- The time complexity of the pop operation is amortized O(1) because each element is transferred between stacks at most once.
Pop 操作的时间复杂度是多少?
- Pop 操作的时间复杂度是均摊 O(1),因为每个元素在栈之间的转移最多只发生一次。
-
Can you optimize the space complexity of this implementation?
- The space complexity is already optimal, as it uses O(n) space, where n is the number of elements in the queue.
你能优化此实现的空间复杂度吗?
- 空间复杂度已经是最优的,因为它使用 O(n) 空间,其中 n 是队列中的元素数量。
-
How does this approach differ from using a single stack?
- Implementing a queue with a single stack is not straightforward because it requires additional logic to maintain the order of elements for FIFO behavior.
这种方法与使用单个栈有何不同?
- 使用单个栈实现队列并不简单,因为它需要额外的逻辑来维护元素的顺序以实现 FIFO 行为。
-
What are the trade-offs of using this method to implement a queue?
- The trade-off is that while push is efficient, pop and peek operations require transferring elements between stacks, leading to amortized O(1) complexity.
使用这种方法实现队列的权衡是什么?
- 权衡在于虽然 push 操作是高效的,但 pop 和 peek 操作需要在栈之间转移元素,导致均摊 O(1) 的复杂度。
Conclusion
Implementing a queue using two stacks is a practical and efficient way to achieve FIFO behavior with LIFO structures. It ensures that operations remain efficient while maintaining the order of elements.
结论
使用两个栈实现队列是一种实用且高效的方法,可以通过 LIFO 结构实现 FIFO 行为。它确保在维护元素顺序的同时保持操作的高效性。
Leave a Reply