力扣面试03.04题:用栈实现队列 - 双栈解法详解
6个月前 (06-02)

内容简介
本文详细解析了力扣面试03.04题"用栈实现队列"的双栈解法。通过两个栈的巧妙配合,实现了队列的先进先出(FIFO)特性。文章包含完整注释代码、算法思路讲解和复杂度分析,帮助读者掌握栈与队列相互转换的核心技巧。
算法思路
1.双栈结构:使用输入栈s1和输出栈s2
2.入队操作:直接压入输入栈s1
3.出队操作:当输出栈s2为空时,将输入栈s1的所有元素弹出并压入s2
4.队首元素:与出队操作类似,但不移除元素
5.判空条件:两个栈同时为空时队列为空
代码实现(带详细注释)
class MyQueue {
public:
stack<int> s1; // 输入栈,负责接收push操作
stack<int> s2; // 输出栈,负责pop和peek操作
MyQueue() {
// 构造函数,无需特殊初始化
}
// 入队操作:直接压入输入栈
void push(int x) {
s1.push(x);
}
// 出队操作:移除并返回队首元素
int pop() {
// 如果输出栈为空,将输入栈元素全部转移到输出栈
if(s2.empty()) {
while(!s1.empty()) {
s2.push(s1.top()); // 将s1栈顶元素压入s2
s1.pop(); // 弹出s1栈顶元素
}
}
int res = s2.top(); // 获取输出栈栈顶元素
s2.pop(); // 弹出输出栈栈顶元素
return res; // 返回队首元素
}
// 获取队首元素但不移除
int peek() {
// 如果输出栈为空,将输入栈元素全部转移到输出栈
if(s2.empty()) {
while(!s1.empty()) {
s2.push(s1.top());
s1.pop();
}
}
return s2.top(); // 返回输出栈栈顶元素
}
// 判断队列是否为空
bool empty() {
return s1.empty() && s2.empty(); // 两个栈都为空时队列为空
}
};复杂度分析
push操作:O(1),直接压入输入栈
pop/peek操作:均摊O(1),最坏情况下O(n)
空间复杂度:O(n),需要两个栈存储所有元素
优化方向
延迟转移:只在需要时才转移元素,减少不必要的操作
代码复用:将元素转移逻辑提取为单独函数
异常处理:添加对空队列pop/peek操作的处理
总结
双栈实现队列是数据结构转换的经典问题,通过输入栈和输出栈的配合,巧妙地用后进先出(LIFO)的栈实现了先进先出(FIFO)的队列特性。理解这种解法有助于掌握栈和队列的核心概念及其相互转换技巧。
原创内容 转载请注明出处

