当前位置:首页 > 力扣 > 力扣面试03.04题:用栈实现队列 - 双栈解法详解

力扣面试03.04题:用栈实现队列 - 双栈解法详解

2个月前 (06-02)

力扣面试03.04题:用栈实现队列 - 双栈解法详解 栈实现队列  双栈算法 队列数据结构 算法面试题解 第1张

内容简介

本文详细解析了力扣面试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)的队列特性。理解这种解法有助于掌握栈和队列的核心概念及其相互转换技巧。


原创内容 转载请注明出处

分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。