演算法學習,演算法學習網站

來源:互聯網
上載者:User

演算法學習,演算法學習網站
最小棧

最小棧其實和棧沒有什麼區別的,唯一的區別在於最小棧是可以在O(1)時間內得到當前的棧空間裡,最小的值是多少。

最小棧的操作

最小棧的操作和普通棧的操作沒有太大區別,唯一多了一個方法就是getMin()方法,這個方法是用來擷取當前棧內的最小值。其他方法就是Push(), Pop(), Top()...等

在O(n)時間內找到新的最小值

這裡就厲害了,先說普通的O(n)的方法~得到棧內最小值。是不是只要維護一個Min的變數就可以呢?不僅僅是!下面舉例說明。

  • 首先:我們設定一個棧,和一個變數int Min儲存最小值。
  • 然後:假設我們的操作為-Push(1),Push(2),Push(3),Push(-1),Push(4)
  • 現在:我們來看下堆棧和Min的變化。
      stack   1    2    3    -1     4   Min    1    1    1    -1    -1

我們發現Min值是在第一次插入1的時候為1,第4次插入-1的時候變為-1,這個時候我們是不是覺得很簡單,只用維護一個Min就可以了?不是的!假設我們進行操作:Pop(),Pop()操作。我們來看看堆棧裡剩下了什麼。

      stack   1   2   3

那麼Min呢?還是-1,但其實-1已經被Pop()掉了。假如我們發現最小值被Pop()之後,我們如何更新Min呢?只能從頭遍曆,那麼就需要O(n)的時間。

O(1)的辦法

這裡說下如何O(1)時間內就找到,維護的變數沒有變化,但是我們在堆棧記憶體放的元素需要與Min值產生關聯。
例子:
我們進行同樣的5次Push操作,壓棧順序為1 2 3 -1 4

  1. 第一次棧存放0, Min為1.
  2. 第二次棧存放2-Min=1, Min<2 所以繼續為1.
  3. 第三次棧存放3-Min=2, Min<3 所以繼續為1.
  4. 第四次棧存放-1-Min=-2, Min>-1 所以Min = -1.
  5. 第五次棧存放4-Min=5, Min<5 所以繼續為-1.

大家看明白沒?我們存放的數為x-Min.
這是Push的操作,當我們進行Pop()的時候怎麼做呢,進行兩次Pop()?

第一次棧頂元素5, 5>0, 彈出,返回 5+Min=4.
第二次棧頂元素-2, -2<0,彈出,返回Min. 並更新Min=Min-(-2).

那Top呢?

假如棧頂元素為5, 5>0 返回5+Min.
假如棧頂元素為-2, -2<0 返回Min.

大家發現沒?實際上我們壓棧的時候,壓入的元素就是X-Min,那麼只要壓入的元素大於Min,那麼存放的都是正數,而當X小於Min的時候,壓入的元素(X-Min)就是負數。

所以彈棧的時候:
遇到正數,直接彈出棧頂元素(X-Min)和Min的和(X-Min+Min)就可以了。
遇到負數,說明在壓入這個元素的時候Min值有更新,那個時候的Min值被更新為新插入的X. 例如Min=1,插入-1的時候,棧存放-1-Min=-2,而Min更新為新的X值(-1).則彈的時候就直接彈出Min就可以了。那麼我們同時也把最小值彈出了,要更新Min,更新為當前Min-(X-下一個Min)此處比較繞,多用例子理解。

代碼實現

我實現了4個版本,其中前兩個版本是O(1)層級的,後兩個是O(n)層級的。第2個版本可能有些瑕疵,假如你們看到代碼哪裡錯誤請評論,多謝。

1號容器實現

自己寫的結構體。

////  main.cpp//  MinStack2////  Created by Alps on 14/12/3.//  Copyright (c) 2014年 chen. All rights reserved.//#include <iostream>#include <vector>using namespace std;class MinStack {public:    vector<int> stack;    int min;    void push(int x) {        if (stack.empty()) {            stack.push_back(0);            min = x;        }else{            stack.push_back(x-min);            if (x < min) {                min = x;            }        }            }        void pop() {        if (stack.empty()) {            return;        }else{            if (stack.back() < 0) {                min = min - stack.back();            }            stack.pop_back();        }    }        int top() {        if (stack.empty()) {            return NULL;        }        if (stack.back() > 0) {            return stack.back()+min;        }else{            return min;        }    }        int getMin() {        if (stack.empty()) {            return NULL;        }        return min;    }};int main(int argc, const char * argv[]) {    // insert code here...    std::cout << "Hello, World!\n";    return 0;}


2號STL的stack實現

在邊緣測試的時候,我的編譯器沒出錯,但是OJ上報WA了。

////  main.cpp//  MinStack4_leetcode////  Created by Alps on 14/12/3.//  Copyright (c) 2014年 chen. All rights reserved.//#include <iostream>#include <stack>using namespace std;class MinStack{public:    stack<long> s;    long min;    void push(int x){        if (s.empty()) {            s.push(0);            min = x;        }else{            s.push(x-min);            if (x < min) {                min = x;            }        }    }        void pop(){        if (s.empty()) {            return;        }else{            if (s.top() < 0) {                min = min - s.top();            }            s.pop();        }    }        int top(){        if (s.empty()) {            return NULL;        }else{            if (s.top() > 0) {                return (int)(min+s.top());            }else{                return (int)min;            }        }    }        int getMin(){        if (s.empty()) {            return NULL;        }else{            return (int)min;        }    }    };int main(int argc, const char * argv[]) {    int a = -2147483648;        MinStack M;    M.push(2147483646);    M.push(2147483646);    M.push(2147483647);    printf("%d\n",M.top());    M.pop();    printf("%d\n",M.getMin());    M.pop();    printf("%d\n",M.getMin());    M.pop();    M.push(2147483647);    printf("%d\n",M.top());    printf("%d\n",M.getMin());    M.push(a);    printf("%d\n",M.top());    printf("%d\n",M.getMin());    M.pop();    printf("%d\n",M.getMin());    return 0;}


3號鏈表實現

自己寫的鏈表結構體。

////  main.cpp//  MinStack3_leetcode////  Created by Alps on 14/12/3.//  Copyright (c) 2014年 chen. All rights reserved.//#include <iostream>using namespace std;class MinStack {public:        struct StackNode{        int num;        StackNode *next;    };    typedef StackNode* stack;    stack s;    MinStack(){        s = (stack)malloc(sizeof(struct StackNode));        s->next = NULL;    }        int min;    void push(int x) {        if (s->next == NULL) {            stack node = (stack)malloc(sizeof(struct StackNode));            node->num = x;            node->next = s->next;            s->next = node;            min = x;        }else{            stack node = (stack)malloc(sizeof(struct StackNode));            node->num = x;            node->next = s->next;            s->next = node;            if (x < min) {                min = x;            }        }    }        void pop() {        if (s->next == NULL) {            return;        }else{            stack temp = s->next;            if (min == s->next->num && s->next->next != NULL) {                                s->next = s->next->next;                free(temp);                min = s->next->num;                for (stack loop = s->next; loop != NULL; loop = loop->next) {                    if (min > loop->num) {                        min = loop->num;                    }                }            }else{                                s->next = s->next->next;                free(temp);            }                    }    }        int top() {        if (s->next == NULL) {            return NULL;        }        return s->next->num;    }        int getMin() {        if (s->next == NULL) {            return NULL;        }        return min;    }};int main(int argc, const char * argv[]) {    MinStack MinS;    MinS.push(-1);    MinS.push(0);    MinS.push(2);    MinS.push(-2);    printf("%d\n",MinS.top());    MinS.pop();    MinS.pop();    MinS.pop();    printf("%d\n",MinS.getMin());    return 0;}


4號容器實現

最古老的版本。

////  main.cpp//  MinStack_leetcode////  Created by Alps on 14/12/2.//  Copyright (c) 2014年 chen. All rights reserved.//#include <iostream>#include "vector"using namespace std;class MinStack {public:    struct StackNode{        int num;        int min;    };    vector<StackNode> stack;    void push(int x) {        if (stack.empty()) {            StackNode S = {x,x};            stack.push_back(S);        }else{            if (x < stack.back().min) {                StackNode S = {x,x};                stack.push_back(S);            }else{                StackNode S = {x,stack.back().min};                stack.push_back(S);            }        }            }        void pop() {        if (stack.empty()) {                    }else{            stack.pop_back();        }    }        int top() {        if (stack.empty()) {            return NULL;        }        return stack.back().num;    }        int getMin() {        if (stack.empty()) {            return NULL;        }        return stack.back().min;    }};int main(int argc, const char * argv[]) {    MinStack minstack;    minstack.push(-1);    minstack.push(1);    printf("%d %d\n",minstack.top(), minstack.getMin());    return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.