[leetcode日記]155.最小棧

題目

設計一個支持 push ,pop ,top 操作,並能在常數時間內檢索到最小元素的棧。

push(x) —— 將元素 x 推入棧中。 pop() —— 刪除棧頂的元素。 top() —— 獲取棧頂元素。 getMin() ——
檢索棧中的最小元素。

示例:

輸入: [“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]

輸出: [null,null,null,null,-3,null,0,-2]

解釋: MinStack minStack = new MinStack(); minStack.push(-2);
minStack.push(0); minStack.push(-3); minStack.getMin(); --> 返回 -3.
minStack.pop(); minStack.top(); --> 返回 0. minStack.getMin();
–> 返回 -2.

提示:

pop、top 和 getMin 操作總是在 非空棧 上調用。

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/min-stack
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

分析

要做出這道題目,首先要理解棧結構先進後出的性質。

對於棧來說,如果一個元素 a 在入棧時,棧裏有其它的元素 b, c, d,那麼無論這個棧在之後經歷了什麼操作,只要 a 在棧中,b, c, d 就一定在棧中,因爲在 a 被彈出之前,b, c, d 不會被彈出。

因此,在操作過程中的任意一個時刻,只要棧頂的元素是 a,那麼我們就可以確定棧裏面現在的元素一定是 a, b, c, d。

那麼,我們可以在每個元素 a 入棧時把當前棧的最小值 m 存儲起來。在這之後無論何時,如果棧頂元素是 a,我們就可以直接返回存儲的最小值 m。

按照上面的思路,我們只需要設計一個數據結構,使得每個元素 a 與其相應的最小值 m 時刻保持一一對應。因此我們可以使用一個輔助棧,與元素棧同步插入與刪除,用於存儲與每個元素對應的最小值。

當一個元素要入棧時,我們取當前輔助棧的棧頂存儲的最小值,與當前元素比較得出最小值,將這個最小值插入輔助棧中;

  • 當一個元素要出棧時,我們把輔助棧的棧頂元素也一併彈出;
  • 在任意一個時刻,棧內元素的最小值就存儲在輔助棧的棧頂元素中。

代碼

#define STACK_MAX 1000

typedef struct {
    int top;
    int data[STACK_MAX];
} MyStack;

typedef struct {
    MyStack stackAll;
    MyStack stackMin;
} MinStack;

MinStack *minStackCreate() {
    MinStack *stack = malloc(sizeof(MinStack));
    stack->stackAll.top = -1;
    stack->stackMin.top = -1;

    return stack;
}

void minStackPush(MinStack *obj, int x) {
    //只判斷stackAll即可,stackMin的數據小於等於stackAll
    if (obj->stackAll.top == (STACK_MAX - 1))
        return;

    //stackAll保存所有數據,都要入棧
    obj->stackAll.data[++obj->stackAll.top] = x;

    //stackMin保存最小數據,入棧前需要判斷棧頂值
    if (-1 == obj->stackMin.top || x <= obj->stackMin.data[obj->stackMin.top]) {
        obj->stackMin.data[++obj->stackMin.top] = x;
    }
}

void minStackPop(MinStack *obj) {
    if (obj->stackAll.top == -1)
        return;

    if (obj->stackAll.data[obj->stackAll.top] == obj->stackMin.data[obj->stackMin.top]) {
        obj->stackMin.top--;
    }
    obj->stackAll.top--;
}

int minStackTop(MinStack *obj) {
    return obj->stackAll.data[obj->stackAll.top];
}

int minStackGetMin(MinStack *obj) {
    return obj->stackMin.data[obj->stackMin.top];
}

void minStackFree(MinStack *obj) {
    free(obj);
}


結果

在這裏插入圖片描述
效果勉強湊活。還有沒有其他方法呢?

分析

上面的解法用了兩個棧,輔助棧的操作比較有限。所以其實一個棧就可以實現兩個棧的作用效果,當push時入棧兩個元素,分別是當前命令需要入棧的元素和棧中所有元素的最小值;出棧的時候同時出兩個元素,丟棄最小值元素,返回所需要的元素;獲取最小值時就需要返回棧中第二個元素。

還有一種是我在棧中記錄最小值,當元素進棧時判斷是否更新最小值,當元素出棧的時候,若出棧元素等於最小值,則進行更新最小值。

這兩種方法中,我感覺後者明顯更優秀,但是後者更新最小值的時候需要遍歷一遍棧中所有元素。代碼如下:

代碼2

typedef struct {
    int val[10000];
    int min;
    int len;
    int count;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() {
    MinStack* obj= (MinStack*)calloc(1,sizeof(MinStack));
    obj->count = 0;
    obj->len = 10000;
    obj->min = INT_MAX;
    return obj;
}

void minStackPush(MinStack* obj, int x) {
    if(obj->count<obj->len){
        obj->val[obj->count++] = x;
        if(obj->min>x)
            obj->min = x;
    }
}

void minStackPop(MinStack* obj) {
    if(obj->count>0){
        obj->count--;
    }
    int x = INT_MAX;
    for(int i = 0;i<obj->count;i++) {
        if(obj->val[i]<x)
            x = obj->val[i];
    }
    obj->min = x;

}

int minStackTop(MinStack* obj) {
    if(obj->count>0)
        return obj->val[obj->count-1];
    return 0;
}

int minStackGetMin(MinStack* obj) {
    if(obj->count>0)
       return obj->min;
    return 0;
}

void minStackFree(MinStack* obj) {
    obj->count = 0;
    obj->min = INT_MIN;

}

運行結果

在這裏插入圖片描述

效果還可以吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章