力扣 155 最小栈

部分思想及代码转载自:https://blog.csdn.net/alps1992/article/details/41741811

一开始忘了考虑最小栈会被退栈以及还会有进栈的数问题代码报废
每次更新 时间复杂度O(n),过高
效率高的方法,时间复杂度O(1).
我们每次入栈的时候,保存的不再是真正的数字,而是它与当前最小值的差(当前元素没有入栈的时候的最小值)。 这样我们pop和top的时候拿到栈顶元素再加上上一个最小值即可。 另外我们在push和pop的时候去更新min,这样getMin的时候就简单了,直接返回min。
O(1)的办法
这里说下如何O(1)时间内就找到,维护的变量没有变化,但是我们在堆栈内存放的元素需要与Min值产生关联。
例子:
我们进行同样的5次Push操作,压栈顺序为1 2 3 -1 4。

第一次栈存放 默认为0, Min为1. 因为此时最小就是第一个元素. 当前1-Min一定为0.
第二次栈存放2-Min=1, Min<2 所以继续为1.
第三次栈存放3-Min=2, Min<3 所以继续为1.
第四次栈存放-1-Min=-2, Min>-1 所以Min = -1.
第五次栈存放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)此处比较绕,多用例子理解。(这两个是一个思路,最后的M-(X-下一个M)的具体意思:
M下其实是上一个M,这个上下是相对概念,即1,
式子展开就是:
力扣 155 最小栈_第1张图片

弹栈时 X-M>0则未更新,直接弹出X
X-M<0,则更新,X

可以加入辅助栈,也可以采用栈的链式存储
代码:
辅助栈:

/***
思路:用两个栈实现。
一个普通栈,一个min栈(普通栈负责数据的入、出,min栈的栈顶永远保存当前元素的最小值)。
第一次入栈时,入到普通栈、min栈中。再次入往普通栈入数据时,当该数据<=min栈栈顶元素时,
也将该数据入到min栈中,否则只入到普通栈中。从普通栈出数据时,该数据==min栈栈顶数据时,
min栈也弹出栈顶元素,否则只弹出普通栈顶元素。总体思想就是min栈用于保存当前数据元素的最小值
**/
typedef struct
{
    int *data1;
    int *data2;
    int top1;//普通
    int top2;//最小

}stack; //两栈

stack *createstack()
{
    stack *obj=(stack*)malloc(sizeof(stack));
    obj->data1=(int *)malloc(sizeof(int)*MAXSIZE);
    obj->top1=-1;
    obj->data2=(int *)malloc(sizeof(int)*MAXSIZE);
    obj->top2=-1;
    return obj;
}
void stackpush(stack *obj,int x)
{
    if(obj->top1==MAXSIZE-1&&obj->top2==MAXSIZE-1)
        return;
    else{
            if(obj->top1==-1&&obj->top2==-1)
            {
                 obj->top1++;//数组下标
        obj->data1[obj->top1]=x;
        obj->top2++;
        obj->data2[obj->top2]=x;
            }
            else if(x<=obj->data2[obj->top2])
            {
                 obj->top1++;
        obj->data1[obj->top1]=x;
        obj->top2++;
        obj->data2[obj->top2]=x;
            }
            else{
                obj->top1++;
        obj->data1[obj->top1]=x;
            }

    }
}
void stackpop(stack *obj)
{
    if(obj->top1==-1&&obj->top2==-1)
    {
        return;
    }
    else if(obj->data1[obj->top1]==obj->data2[obj->top2])
    {
        obj->top1--;
        obj->top2--;
    }
    else{
        obj->top1--;
    }
}
int stacktop(stack *obj)
{
    return obj->data1[obj->top1];
}
int stackgetmin(stack *obj)
{
    return obj->data2[obj->top2];
}

int main()
{
  stack *obj=createstack();
  stackpush(obj,8);
  stackpush(obj,0);
  stackpush(obj,9);
  stackpush(obj,-5);
  stackpop(obj);
  int a=stackgetmin(obj);
  printf("%d\n",a);


}

链栈:

#include 
#include 
#include 
#include 
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;

}

最普通方法:

#include 
#include 
#define MAXSIZE 100

//普通法 时间复杂度O(n)
typedef struct {
  int *data;
  int top;

}minstack;
minstack *minstackinit()
{
    minstack *obj=(minstack *)malloc(sizeof(minstack));
    obj->data=(int *)malloc(sizeof(int)*MAXSIZE);
    obj->top=-1;
    return obj;
}
void minstackpush(minstack *obj,int x)
{
    if(obj->top==MAXSIZE-1)
        return;
    else{
        obj->top++;
        obj->data[obj->top]=x;
    }
}
void minstackpop(minstack *obj)
{
    if(obj->top==-1)
        return;
    else{
        obj->top--;
    }
}
int minstackTop(minstack *obj)
{
    if(obj->top==-1)
        return 0;
    return obj->data[obj->top];
}
int minstackgetmin(minstack *obj)
{

    if(obj->top==-1)
        return 0;
    if(obj->top==0)
        return obj->data[obj->top];
    int min=obj->data[0];
    for(int i=0;i<obj->top;i++)
    {
        if(obj->data[i]<min)
            min=obj->data[i];

    }
    return min;
}
int main()
{
    minstack *obj=minstackinit();

    minstackpush(obj,8);
    minstackpush(obj,21);
    minstackpush(obj,6);
    minstackpop(obj);
    printf("%d\n",minstackTop(obj));
    int a=minstackgetmin(obj);
    printf("%d\n",a);
}

差值法:

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.min = float('inf')
        self.stack = []

    def push(self, x: int) -> None:
        self.stack.append(x - self.min)
        if x < self.min:
            self.min = x

    def pop(self) -> None:
        if not self.stack:
            return
        tmp = self.stack.pop()
        if tmp < 0:
            self.min -= tmp

    def top(self) -> int:
        if not self.stack:
            return
        tmp = self.stack[-1]
        if tmp < 0:
            return self.min
        else:
            return self.min + tmp

    def getMin(self) -> int:
        return self.min

做题确实有助于对知识的理解,栈不管是什么形式构造只要保持其基本特点即可,之前有点拘泥于课本上的形式了
部分代码及思路链接:
https://blog.csdn.net/alps1992/article/details/41741811
https://github.com/azl397985856/leetcode/blob/master/problems/155.min-stack.md

你可能感兴趣的:(力扣,简单)