代码随想录算法训练Day10 LeetCode232. 用栈实现队列(模拟);225.用队列实现栈(模拟)

本文介绍了如何使用栈和队列来模拟它们各自的基本操作。在LeetCode232题中,通过两个栈实现队列,入队操作直接压入栈,出队时将一个栈所有元素移到另一个栈再弹出。而在LeetCode225题中,仅用一个队列就能模拟栈,出栈时将队列内除最后一个元素外的所有元素移回队列尾部。两种方法都巧妙地利用了数据结构特性来完成转换。
摘要由CSDN通过智能技术生成

代码随想录算法训练Day10 | LeetCode232. 用栈实现队列(模拟);225.用队列实现栈(模拟)

两个基本容器的应用,代码不是重点,重要的是要理解关于这两种容器的底层原理和使用方式。

LeetCode232.用栈实现

232. 用栈实现队列 - 力扣(LeetCode)

用两个栈来模拟队列,一个栈负责添加元素,另一个栈负责弹出元素。因为栈是先进后出的,队列是先进先出。在添加元素时,向入栈中添加,出栈时,由入栈向出栈中添加元素,最后弹出出栈中最后一个添加的元素,也就是第一个进栈的元素。通过这样的方式,来模拟队列的顺序。

代码随想录中的详细解释:

在这里插入图片描述

在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。

最后如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。

在代码实现的时候,会发现pop() 和 peek()两个函数功能类似,代码实现上也是类似的,可以思考一下如何把代码抽象一下。

C++代码如下:

class MyQueue {
public:
    stack<int> stIn;
    stack<int> stOut;
    /** Initialize your data structure here. */
    MyQueue() {

    }
    /** Push element x to the back of queue. */
    void push(int x) {
        stIn.push(x);
    }

    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        // 只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
        if (stOut.empty()) {
            // 从stIn导入数据直到stIn为空
            while(!stIn.empty()) {
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int result = stOut.top();
        stOut.pop();
        return result;
    }

    /** Get the front element. */
    int peek() {
        int res = this->pop(); // 直接使用已有的pop函数
        stOut.push(res); // 因为pop函数弹出了元素res,所以再添加回去
        return res;
    }

    /** Returns whether the queue is empty. */
    bool empty() {
        return stIn.empty() && stOut.empty();
    }
};

复杂度分析

入队self.push()

时间复杂度O(1),直接把元素append到stack_in栈中的最后就行;

空间复杂度O(1),stack_in 栈多储存一个元素;

出队self.pop()

时间复杂度O(N),需要把所有元素全部压入stack_out栈中,再出栈一个元素;

空间复杂度O(N)需要额外的N个内存来储存队列中的元素;

取队首元素self.peek()

因为需要调用self.pop(),然后再push,时间复杂度O(N);空间复杂度O(N);

判断空self.empty()

只需要判断两个栈是否为空即可,时间复杂度O(1),空间复杂度O(1)

LeetCode225. 用队列实现栈

225. 用队列实现栈 - 力扣(LeetCode)

利用队列可以循环添加和先进先出的特性,一个队列就可以模拟栈的实现,但是也可以用两个队列。

代码随想录详解:

在这里插入图片描述

用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。

优化

其实这道题目就是用一个队列就够了。

一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。

C++优化代码:

class MyStack {
public:
    queue<int> que;
    /** Initialize your data structure here. */
    MyStack() {

    }
    /** Push element x onto stack. */
    void push(int x) {
        que.push(x);
    }
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int size = que.size();
        size--;
        while (size--) { // 将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部
            que.push(que.front());
            que.pop();
        }
        int result = que.front(); // 此时弹出的元素顺序就是栈的顺序了
        que.pop();
        return result;
    }

    /** Get the top element. */
    int top() {
        return que.back();
    }

    /** Returns whether the stack is empty. */
    bool empty() {
        return que.empty();
    }
};

复杂度分析

入栈self.push()

时间复杂度O(1),直接把元素append到queue中的最后就行;

空间复杂度O(1),queue 栈多储存一个元素;

出栈self.pop()

时间复杂度O(N),需要把除最后一个元素之外的所有元素全部弹出再压入队列中

空间复杂度O(N)需要额外的N个内存来储存栈中的元素;

取栈首元素self.top()

直接用deque的-1下标,时间复杂度O(1);空间复杂度O(1);

判断空self.empty()

op()**

时间复杂度O(N),需要把除最后一个元素之外的所有元素全部弹出再压入队列中

空间复杂度O(N)需要额外的N个内存来储存栈中的元素;

取栈首元素self.top()

直接用deque的-1下标,时间复杂度O(1);空间复杂度O(1);

判断空self.empty()

只需要判断队列是否为空即可,时间复杂度O(1),空间复杂度O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值