代码随想录算法训练营day10

题目:232.用栈实现队列、225. 用队列实现栈

参考链接:代码随想录

基础知识

cpp中的stack和queue,底层实现是deque即双向队列,不允许使用迭代器便利。栈和队列并不被归类为容器,而被视为容器适配器
回顾基本操作
栈:

s.push(x);
s.pop();//只出栈并不返回
s.top();
s.empty();
s.size();

队列:

q.push();
q.pop();//同样不返回
q.size();
q.empty();
q.front();
q.back();

232.用栈实现队列

思路:本题主要考察对栈和队列的理解程度。首先队列为先进先出,栈为先进后出,故我们使用两个栈s1和s2,s1用于输入,s2用于输出。当元素入队时,按顺序进入s1;当元素需要出队时,将s1中所有元素都出栈放入s2中,再将s2顶部元素出栈即可。弄明白了这个过程,代码就很容易写出。

class MyQueue {
public:
    stack<int> s1,s2;//定义两个栈,一个进一个出
    MyQueue() {

    }
    
    void push(int x) {
        s1.push(x);
    }
    
    int pop() {
        if(s2.empty()){//s2为空则把s1全部加入s2
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }
        }
        int ret=s2.top();
        s2.pop();
        return ret;
    }
    
    int peek() {
        if(!s2.empty()){
            return s2.top();
        }
        else{
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }
            return s2.top();
        }
    }
 
    bool empty() {
        return (s1.empty() && s2.empty());
    }
};

对比标答,我的peek()写复杂了,因为peek()需要返回队头元素即pop()出去的结果,可以直接调用pop(),然后再将其塞回去s2。主要是同样的代码避免了重复实现,这是个很重要的习惯。
标答:

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

225. 用队列实现栈

思路:本题也不是很难。但是如果按照前一题一样的思想,一个用于in一个用于out,其实无法实现。
仔细想,如果1,2,3分别进入一个队列后,如果需要按照先进后出的原则出3,则需要将1和2都拿走,然后只剩下一个3,最后再将3出队。此时q1就是完全存放了栈中的元素,而q2仅仅是做了一个临时备份的作用,将1和2放入q2中,当pop()完成后,再将q2中元素放回q1即可。

class MyStack {
public:
    queue<int> q1,q2;
    MyStack() {

    }
    
    void push(int x) {
        q1.push(x);
    }
    
    int pop() {
        while(q1.size()>1){//q1多于1个元素
            q2.push(q1.front());
            q1.pop();
        }
        int ret=q1.front();
        q1.pop();
        while(!q2.empty()){//q2中元素放回q1
            q1.push(q2.front());
            q2.pop();
        }
        return ret;
    }
    
    int top() {
        int ret=this->pop();//这次记得复用代码
        q1.push(ret);
        return ret;
    }
    
    bool empty() {
        return q1.empty();//这里只要看q1
    }
};

虽然成功运行,但和标答还有很大差距,首先是在pop()中,我每次while都判断q1.size(),导致时间复杂度变为O(n^2),实际上应该将size先记录,采用size–的方式,此时时间复杂度为O(n)。对于q2到q1也可以直接赋值,不用一个个push()。然后是top(),这里可以直接调用q1的**back()**函数,时间复杂度为O(1),我先调用了pop()导致时间复杂度为O(n)。
修改后:

int pop() {
    int size = que1.size();
    size--;
    while (size--) { // 将que1 导入que2,但要留下最后一个元素
        que2.push(que1.front());
        que1.pop();
    }
    int result = que1.front(); // 留下的最后一个元素就是要返回的值
    que1.pop();
    que1 = que2;            // 再将que2赋值给que1
    while (!que2.empty()) { // 清空que2
        que2.pop();
    }
    return result;
}
/** Get the top element. */
int top() {
    return que1.back();
}

看解析还有只用一个queue的思路。其实就是每次pop()的时候将整个队列翻一圈,思路是一样的。

class MyStack {
public:
    queue<int> q1;
    MyStack() {

    }
    
    void push(int x) {
        q1.push(x);
    }
    
    int pop() {
        int size=q1.size();
        while(size>1){//q1多于1个元素
            q1.push(q1.front());
            q1.pop();
            size--;
        }
        int ret=q1.front();
        q1.pop();
        return ret;
    }
    
    int top() {
        return q1.back();
    }
    
    bool empty() {
        return q1.empty();//这里只要看q1
    }
};
  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值