1. 栈与队列基础:数据结构特性与相互转换
栈和队列是计算机科学中最基础的两种线性数据结构,它们在算法设计和系统开发中有着广泛应用。栈遵循后进先出(LIFO)原则,而队列遵循先进先出(FIFO)原则。理解它们的核心差异和相互转换方法,是算法学习的重要基础。
1.1 用栈实现队列(LeetCode 232)
实现思路的核心在于使用两个栈(stack_in和stack_out)来模拟队列的FIFO特性。当需要pop或peek操作时,如果输出栈为空,就将输入栈的所有元素"倒置"到输出栈中,这样最先进入的元素就会位于输出栈的顶部。
python复制class MyQueue:
def __init__(self):
self.stack_in = [] # 负责接收push操作
self.stack_out = [] # 负责提供pop/peek操作
def push(self, x):
self.stack_in.append(x) # 直接压入输入栈
def pop(self):
if self.empty():
return None
self._transfer_if_needed() # 必要时转移元素
return self.stack_out.pop() # 弹出输出栈顶部
def peek(self):
if self.empty():
return None
self._transfer_if_needed()
return self.stack_out[-1] # 查看但不弹出
def empty(self):
return not self.stack_in and not self.stack_out
def _transfer_if_needed(self):
"""私有方法:当输出栈空时,将输入栈元素转移过来"""
if not self.stack_out:
while self.stack_in:
self.stack_out.append(self.stack_in.pop())
时间复杂度分析:
- push操作:O(1)
- pop/peek操作:均摊O(1)(虽然有时需要O(n)转移,但每个元素只会被转移一次)
关键技巧:将昂贵的转移操作分摊到多个pop操作上,确保大多数情况下操作都是O(1)复杂度。
1.2 用队列实现栈(LeetCode 225)
与前一问题相反,这里需要用队列的FIFO特性模拟栈的LIFO行为。核心思路是维护一个主队列,在每次push操作时,通过辅助队列将新元素调整到队列前端。
python复制from collections import deque
class MyStack:
def __init__(self):
self.q1 = deque() # 主队列
self.q2 = deque() # 辅助队列
def push(self, x):
self.q2.append(x) # 新元素先入辅助队列
while self.q1: # 将主队列元素转移到辅助队列
self.q2.append(self.q1.popleft())
self.q1, self.q2 = self.q2, self.q1 # 交换角色
def pop(self):
return self.q1.popleft() if self.q1 else None
def top(self):
return self.q1[0] if self.q1 else None
def empty(self):
return not self.q1
优化版本(单队列实现):
python复制class MyStack:
def __init__(self):
self.q = deque()
def push(self, x):
self.q.append(x)
