設計包含min函數的棧

題目: 設計一個棧,使得PUSH、POP以及GetMin(獲取棧中最小元素)可以在常數時間內完成。函數

分析: 很剛開始很容易想到一個方法,那就是額外創建一個最小堆保存全部元素,這樣每次獲取最小元素只須要O(1)的時間。可是這樣的話,PUSH和POP操做就須要O(lgn)的時間了(假定棧中元素個數爲n),不符合題目的要求。 那麼用1個輔助棧如何呢?設計

解法: 使用一個輔助棧來保存最小元素,這個解法簡單不失優雅。設該輔助棧名字爲minimum stack,其棧頂元素爲當前棧中的最小元素。這意味着 要獲取當前棧中最小元素,只須要返回minimum stack的棧頂元素便可。 每次執行push操做,檢查push的元素是否小於或等於minimum stack棧頂元素。若是是,則也push該元素到minimum stack中。 當執行pop操做的時候,檢查pop的元素是否與當前最小值相等。若是相同,則須要將改元素從minimum stack中pop出去。 代碼: [cpp] view plain copy struct StackGetMin {
void push(int x) {
elements.push(x);
if (minStack.empty() || x <= minStack.top()) //push的元素小於當前minStack的最小元素,則push到minStack中
minStack.push(x);
}
bool pop() {
if (elements.empty()) return false;
if (elements.top() == minStack.top()) //若是原始棧棧頂元素與minStack棧頂元素相同,則將該元素也從minStack中pop出去。
minStack.pop();
elements.pop();
return true;
}
bool getMin(int &min) {
if (minStack.empty()) {
return false;
} else {
min = minStack.top();
return true;
}
}
stack<int> elements;
stack<int> minStack;
};element

實例: 假定有元素3, 2, 5, 4, 2, 1依次入棧,則原始棧中元素爲(1), 輔助棧中元素爲(2) 1
2
4 1 5 2 2 2 3 3 (1) (2) 這樣,第1次pop時,1從兩個棧都pop出去;第2次pop時,2從兩個棧都pop出去;第3次pop,元素4從原始棧pop出去,輔助棧不用pop;第4次pop,元素5從原始棧pop出去,輔助棧不需pop;第5次pop,元素2從兩個棧pop出去;第6次pop,元素3從兩個棧都pop出去。咱們能夠發現,每次push或者pop後,輔助棧的棧頂元素老是當前棧的最小元素。get

另外一解法(不用輔助棧) 另一種解法利用存儲差值而不須要輔助棧,方法比較巧妙。其中須要說明的幾點: push(int elem)函數在棧中壓入當前元素與當前棧中最小元素的差值,而後經過比較當前元素與當前棧中最小元素大小,並將它們中間的較小值壓入。 pop()函數執行的時候,先pop出棧頂的兩個值,這兩個值分別是當前棧中最小值min和最後壓入的元素與棧中最小值的差值diff。若是diff<0,則表示最後壓入棧的元素是最小的元素,所以只需將min-diff壓入棧中,並將min值返回便可。min-diff就是當前元素彈出後,棧中剩下元素的最小值。而若是diff>=0且棧不爲空,則表示當前值不是最小值,因此須要在棧中壓入最小值min並將diff+min返回;若是棧爲空,則表示已是最後一個數字,直接返回min便可。 [cpp] view plain copy stack<int> s;
void push(int elem)
{
if (s.empty()) {
s.push(elem);
s.push(elem);
} else {
int min = s.top();
s.pop();
s.push(elem - min);
s.push(elem < min ? elem : min);
}
}方法

int pop()
{
int min = s.top();
s.pop();
int diff = s.top();
s.pop();
if (diff < 0) {
s.push(min - diff);
return min;
} else {
if (!s.empty()) {
s.push(min);
return diff + min;
}
return min;
}
}im

int min()
{
int min = s.top();
return min;
}top

一個實例以下: clear(): [ ] push(3): [3 3] push(4): [3 1 3] push(2): [3 1 -1 2] push(5): [3 1 -1 3 2] push(1): [3 1 -1 3 -1 1] push(1): [3 1 -1 3 -1 0 1] push(6): [3 1 -1 3 -1 0 5 1] push(7): [3 1 -1 3 -1 0 5 6 1] min() --> 1; pop() --> 7: [3 1 -1 3 -1 0 5 1] min() --> 1; pop() --> 6: [3 1 -1 3 -1 0 1] min() --> 1; pop() --> 1: [3 1 -1 3 -1 1] min() --> 1; pop() --> 1: [3 1 -1 3 2] min() --> 2; pop() --> 5: [3 1 -1 2] min() --> 2; pop() --> 2: [3 1 3] min() --> 3; pop() --> 4: [3 3] min() --> 4; pop() --> 3: [ ]di

參考資料: 設計包含min的棧另解時間

相關文章
相關標籤/搜索