力扣-232. 用棧實現佇列

DawnTraveler發表於2024-05-10

1.題目資訊

2.題解

2.1 雙棧的使用(用棧實現佇列)

思路

我們一開始可能會想到對於每次入棧操作——由於我們可能希望他是加在隊尾(棧底)而不是隊頭(棧首),
所以我們就進行一次首尾互換,將instack中的資料倒騰到outstack,由於棧先進後出的特性,所以這時候原來的棧底在頭部,我們直接將元素push進入就到了棧尾(隊尾)
然後我們再將outstack中的資料倒騰到instack中即可,這樣就又維護了棧原本的順序

程式碼(核心)

        while (!st1.empty()) {
            st2.push(st1.top());
            st1.pop();
        }
        st2.push(x);
        while (!st2.empty()) {
            st1.push(st2.top());
            st2.pop();
        }

2.2 雙棧的使用(最佳化)

思路

我們當然發現每次入棧,都要將所有資料從一個棧中移動到另一個棧中兩次,這樣的工作量實在太大,能否簡化?
我們這樣思考:
1.對於push操作,我們就正常向instack中push資料(這樣是能夠正確儲存順序的)
2.對於pop/top操作,如果outstack為空,我們將instack中所有資料倒騰進去,然後棧尾(隊首)資料就在頭部了,我們就可以取出
如果outstack不為空,為了維護outstack中原有資料順序,我們並不著急將資料倒騰進去,而是等待棧空後再倒騰,現在outstack中的資料就足夠我們操作了

總結:我們很容易發現相對於之前的每讀入一個資料就要操作兩次棧,這裡對於outstack棧空的判斷無疑大大減少了操作次數

程式碼

class MyQueue {
private:
    stack<int> inStack, outStack;
    void in2out() {
        while (!inStack.empty()) {
            outStack.push(inStack.top());
            inStack.pop();
        }
    }

public:
    MyQueue() {}

    void push(int x) { inStack.push(x); }

    int pop() {
        if (outStack.empty()) {
            in2out();
        }
        int x = outStack.top();
        outStack.pop();
        return x;
    }

    int peek() {
        if (outStack.empty()) {
            in2out();
        }
        int x = outStack.top();
        return x;
    }

    bool empty() {
        return inStack.empty() && outStack.empty();
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

相關文章