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();
*/