题目
实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间复杂度为O(1)
GitHub地址
https://github.com/zouchanglin/MinStack
分析
结构设计
- 本题目的实现思路比较简单,使用两个栈,一个栈是用来存储数字,就是普通的数据,在代码中这个栈为
Stack
- 结构体的设计:数字+出现次数,另一个栈便用来存储结构体,在代码中这个栈为
NumStack
,这个栈的栈顶永远存的是Stack
栈中的最小值和最小值个数构成的结构体 - 所以我们将要设计的这个栈命名为
DoubleStack
,提供入栈,出栈,返回最小值得接口和其它基本接口
入栈
- 首先我们先考虑入栈,入栈的时候呢,对于Stack肯定是必须要入栈的,对于NumStack的话就需要考虑了,如果NumStack是空栈,那么肯定是第一次进入元素,所以两个栈都要存东西,而且对于第一次存入的应该将最小值对应的结构体设置为1
- 如果
NumStack
栈不为空的话,那么在压栈之前就需要比较大小,如果比NumStack
栈栈顶元素还小的话就需要将这个较小值压栈,如果相等的话就对栈顶元素的结构体的num+1即可!
出栈
- 首先还是先要获取栈顶元素,因为不是每一次入
Stack
栈的元素都能存入到NumStack
中,所以要出栈的元素和NumStack
的栈顶相等的话就将对应的结构体的count属性-1,要是count原本就是1,那么直接将此元素在NumSatck
中出栈即可! - 上一步只是判断
NumStack
中的元素是否需要出栈,但是将Stack
中的元素出栈是必要的,所以最后将Stack
中的元素弹栈!
GIF演示过程
入栈
出栈
核心代码
void DoubleStackPush(DoubleStack* ds, IDataType x)
{
SDataType s;
SDataType ret;
assert(ds);
//如果结构体栈为空
if(NStackEmpty(&ds->nst) == 0)
{
s.count = 1;
s.num = x;
StackPush(&ds->st,x);
NStackPush(&ds->nst, s);
}
else
{
StackPush(&ds->st, x);
//如果入栈的元素小于最小值记录栈的栈顶
if(x < NStackTop(&ds->nst).num)
{
s.num = x;
s.count = 1;
//将此元素的对应结构体入栈
NStackPush(&ds->nst, s);
}
else if (x == NStackTop(&ds->nst).num)
{
//相等的情况
ret = NStackTop(&ds->nst);
NStackPop(&ds->nst);
ret.count += 1;
NStackPush(&ds->nst, ret);
}
}
}
void DoubleStackPop(DoubleStack* ds)
{
SDataType ret;
assert(ds);
//先获取结构体栈的栈顶元素
ret = NStackTop(&ds->nst);
//如果像个相等就做结构体计数-1或者出栈操作
if(ret.num == StackTop(&ds->st))
{
if(ret.count == 1)
{
NStackPop(&ds->nst);
}
else
{
ret.count--;
NStackPop(&ds->nst);
NStackPush(&ds->nst, ret);
}
}
//将原本存数字出栈
StackPop(&ds->st);
}