1. 程式人生 > >[LeetCode] Implement Stack using Queues 用佇列來實現棧

[LeetCode] Implement Stack using Queues 用佇列來實現棧

Implement the following operations of a stack using queues.

  • push(x) -- Push element x onto stack.
  • pop() -- Removes the element on top of the stack.
  • top() -- Get the top element.
  • empty() -- Return whether the stack is empty.

Notes:

  • You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack).
  • Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue -- which means only push to backpop from frontsize, and is empty operations are valid.

Credits:
Special thanks to 

@jianchao.li.fighter for adding this problem and all test cases.

這道題讓我們用佇列來實現棧,佇列和棧作為兩種很重要的資料結構,它們最顯著的區別就是,佇列是先進先出,而棧是先進後出。題目要求中又給定了限制條件只能用queue的最基本的操作,像back()這樣的操作是禁止使用的。那麼怎麼樣才能讓先進先出的特性模擬出先進後出呢,這裡就需要另外一個佇列來輔助操作,我們總共需要兩個佇列,其中一個佇列用來放最後加進來的數,模擬棧頂元素。剩下所有的數都按順序放入另一個佇列中。當push操作時,將新數字先加入模擬棧頂元素的佇列中,如果此時佇列中有數字,則將原本有的數字放入另一個隊中,讓新數字在這隊中,用來模擬棧頂元素。當top操作時,如果模擬棧頂的隊中有數字則直接返回,如果沒有則到另一個佇列中通過平移數字取出最後一個數字加入模擬棧頂的佇列中。當pop操作時,先執行下top()操作,保證模擬棧頂的佇列中有數字,然後再將該數字移除即可。當empty操作時,當兩個佇列都為空時,棧為空。程式碼如下:

解法一:

class Stack {
public:
    // Push element x onto stack.
    void push(int x) {
        q2.push(x);
        while (q2.size() > 1) {
            q1.push(q2.front());
            q2.pop();
        }
    }

    // Removes the element on top of the stack.
    void pop(void) {
        top();
        q2.pop();
    }

    // Get the top element.
    int top(void) {
        if (q2.empty()) {
            for (int i = 0; i < (int)q1.size() - 1; ++i) {
                q1.push(q1.front());
                q1.pop();
            }
            q2.push(q1.front());
            q1.pop();
        }
        return q2.front();
    }

    // Return whether the stack is empty.
    bool empty(void) {
        return q1.empty() && q2.empty();
    }
    
private:
    queue<int> q1, q2;
};

這道題還有另一種解法,可以參見另一道類似的題Implement Queue using Stacks 用棧來實現佇列,我個人來講比較偏愛下面這種方法,比較好記,只要實現對了push函式,後面三個直接呼叫佇列的函式即可。這種方法的原理就是每次把新加入的數插到前頭,這樣佇列儲存的順序和棧的順序是相反的,它們的取出方式也是反的,那麼反反得正,就是我們需要的順序了。我們需要一個輔助佇列tmp,把s的元素也逆著順序存入tmp中,此時加入新元素x,再把tmp中的元素存回來,這樣就是我們要的順序了,其他三個操作也就直接呼叫佇列的操作即可,參見程式碼如下:

解法二:

class Stack {
public:
    // Push element x onto stack.
    void push(int x) {
        queue<int> tmp;
        while (!q.empty()) {
            tmp.push(q.front());
            q.pop();
        }
        q.push(x);
        while (!tmp.empty()) {
            q.push(tmp.front());
            tmp.pop();
        }
    }

    // Removes the element on top of the stack.
    void pop() {
        q.pop();
    }

    // Get the top element.
    int top() {
        return q.front();
    }

    // Return whether the stack is empty.
    bool empty() {
        return q.empty();
    }
    
private:
    queue<int> q;
};