部分思想及代码转载自: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,
式子展开就是:
弹栈时 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
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