[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;

}

运行结果

在这里插入图片描述

效果还可以吧。

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