leetcode c语言题解(4)——栈和队列互相实现的优化版

栈和队列互相实现

FIFO和FILO,相当于+-号,互转都是利用“负负得正”的原理。

1. 栈实现队列

官方解答中第二种思路很6,按需反转,这样摊还分析下来,复杂度变成了O(1)

class MyQueue {
private:
    stack<int> s1;
    stack<int> s2;
public:
    /** Initialize your data structure here. */
    MyQueue() {}
    
    /** Push element x to the back of queue. */
    void push(int x) {
        s1.push(x);    
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        int ret=0;
    notempty:
        if(!s2.empty()){
            ret = s2.top();
            s2.pop();
            return ret;
        }
        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        //return pop();
        goto notempty;
    }
    
    /** Get the front element. */
    int peek() {
        int ret=0;
    notempty:
        if(!s2.empty()) return s2.top();

        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        goto notempty;
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return s1.empty() && s2.empty();
    }
};

2. 队列实现栈

官方解答中提供了三种思路,我用的方法和方法三很像,又同时做了一点点优化:

  1. 官方方法三
    • 入栈O(N)
    • 出栈O(1)
  2. 我的方法四 (其实思路一样, 就是pop时才去排序.)
    • 入栈O(1)
    • 出栈O(N),
  3. 方法四的优化
    • 入栈O(1)
    • 出栈: 最坏的情况O(N),最好的情况实际pop次数为0
    • 缺点: 需要自定义结构体标记

https://leetcode-cn.com/problems/implement-stack-using-queues/solution/c-dan-dui-lie-de-you-hua-ban-zui-hao-de-qing-kuang/

2.1 方法四

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

    }
    
    /** Push element x onto stack. */
    void push(int x) {
        buf.push(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int size = buf.size();
        int ret = buf.back();
        while(--size>=0){
            if(size!=0) buf.push(buf.front());  
            buf.pop();
        }
        return ret;
    }
    
    /** Get the top element. */
    int top() {
        return buf.back();
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return buf.empty();
    }
};

2.2 方法四的优化版

思路就是:

  1. 用自定义结构体中的flag成员标记当前队列中元素是否有效, 如果是false,则相当于已经被pop(实际并不用pop)
  2. push直接添加,略
  3. pop时
    • 如果back().falg==true,我们直接修改其为false,标记其已经无效了
    • 否则,说明倒数两个需要被删除, 按照单队列思路,头循环加到尾部,然后把最后两个都直接pop掉(因为最后一个已经被标记为false,而现在又pop一次,所以两个都直接pop)
  4. top时,类似pop的处理方法
  • 最坏的情况:连续pop,但是即使这样pop依然是O(N)
  • 最好的情况: push一次,pop一次, 这样实际pop次数为0
  • 混合情况: 优于单队列
typedef struct {
    int val;
    bool flag;
}myint;
class MyStack {
private:
    queue<myint> buf;
public:
    /** Initialize your data structure here. */
    MyStack() {

    }
    
    /** Push element x onto stack. */
    void push(int x) {
        myint mx = {x, true};
        buf.push(mx);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        if(buf.back().flag == true) {
            buf.back().flag=false;
            return buf.back().val;
        }
        
        int size = buf.size();
        while(--size>=2){
            buf.push(buf.front());
            buf.pop();
        }
        int ret = buf.front().val;
        buf.pop();
        buf.pop();

        return ret;
    }
    
    /** Get the top element. */
    int top() {
        if(buf.back().flag==true) return buf.back().val;

        int size = buf.size();
        while(--size>=1){
            buf.push(buf.front());
            buf.pop();
        }
        buf.pop();
        return buf.back().val;
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return (buf.empty() || (!buf.front().flag));
    }
};

猜你喜欢

转载自www.cnblogs.com/whuwzp/p/stack-queue.html