思路:
push,pop操作在常量時間複雜度內完成,沒有問題,但是,min操作需要在常量時間複雜度內完成,一開始很容易想到在棧中儲存一個變數min,用來儲存最小值,那麼如果需要min()操作時,只需要查min變數的值即可.這個思路看起來不錯,但是,有一個致命的缺陷,那就是,只儲存一個min變數,那麼當min也需要彈棧的時候,那麼棧中的min也需要用次二小的值更新,但是,此時無法知道第二個小值是哪個,OK,我們也可以試圖儲存第二小的變數secMin,當最小值彈棧的時候,我們就用secMin去更新min變數,但是,此時,secMin也應該需要ThirdMin更新才行,如果ThirdMin也出棧.......這樣下去,我們就需要儲存min,secMin,ThirdMin......等所有小值.因此用儲存常量個變數的辦法顯然無法滿足.我們可以嘗試用一種資料結構來儲存這一系列的最小值.
現在的問題變成了,我們需要一個額外的空間來儲存當前的最小值,即使當前的最小值出棧了,我們依然可以得到最新當前的最小值(無論彈棧,壓棧的過程如何變化),
我們可以嘗試用輔助棧的辦法來解決:
在新定義的棧中儲存一個資料棧和一個輔助棧.輔助棧棧頂儲存的是當前的最小值min.
min()操作時:只需要查輔助棧頂元素
push( _val )操作時:先將_val壓入資料棧,再比較_val和輔助棧頂元素Top,如果_val < Top,則_val壓進輔助棧,使得_val成為當前的最小值
pop()操作時:先將資料棧頂元素彈棧,如果棧頂元素是最小值,彈了輔助棧頂元素(彈出最小值min)
代碼如下:
#include<iostream>#include<stack>using namespace std;struct MinStack{private:stack<int> St;stack<int> Extern;public:void push(int val){St.push(val);if(Extern.empty() || val <= Extern.top())Extern.push(val);}int pop(){if(St.empty()){cout<<"Hello"<<endl;throw "Error";}int Temp=St.top();St.pop();if(Temp == Extern.top())Extern.pop();return Temp;}int min(){if(Extern.empty()){cout<<"Hello2"<<endl;throw "error!";}return Extern.top();}};void main(){MinStack ms;ms.push(2);ms.push(2);ms.push(3);ms.pop();ms.pop();ms.pop();cout<<ms.min();}
還有一種巧妙的解法:
因為需要在theta(1)時間複雜度內完成min()操作,因此,我們可以想方設法把min置於棧頂,但是,push()操作和pop()操作也需要在theta(1)時間複雜度內完成,怎麼辦呢?先考慮pop(),如果棧頂元素正是最小元素.彈棧只需要把min彈出即可,如果棧頂元素element比min大,怎麼辦呢?我們可以在min的下一個元素儲存element-min,彈棧時可以彈出兩個元素,再算二者之和即可.(思考:element有可能比min小嗎?不可能,因為min是最小值)
push( _val )時,因為這裡的棧操作都是兩個元素一起來的,當棧為空白時,_val進棧兩次,棧頂為最小值min.當棧不為空白時,將棧頂元素min替換成(_val-min )和min{_val,min}
具體操作是:min出棧,push(_val-min),push(_val < min?_val : min)
代碼:
#include<iostream>#include<stack>using namespace std;struct MinStack{private:stack<int> St;public:void push(int val){if(St.empty()){St.push(val);St.push(val);}else{int min=St.top();St.pop();St.push(val-min);St.push(val < min ? val : min);}}int pop(){if(St.empty()){cout<<"Pop Error!"<<endl;exit(1);}int min = St.top(); St.pop();int flag = St.top(); St.pop();//彈棧一彈彈兩個if (flag < 0) //flag< 0,說明彈出的是最小值,需要用次二小值更新棧頂{ St.push(min - flag); return min; } else { //彈出的不是最小值,則直接彈出棧,無需更新最小值if (!St.empty()) { St.push(min); return flag + min; } return min; } }int Min(){if(St.empty()){cout<<"Search Min Error!"<<endl;exit(1);}int min=St.top();return min;}};void main(){MinStack ms;ms.pop();ms.pop();ms.pop();cout<<ms.Min();}