问题描述
思路
根据题目要求在实现栈的同时需要在常数时间范围内找到栈中最小的元素,首先想到的就是在创建一个辅助栈,该栈按照元素从小到大的顺序排列,在pop和push时对这辅助栈进行调整,所以栈顶永远是最小元素,满足题目要求。
代码
数据结构定义
struct node{
int val;
struct node* next;
};
typedef struct node* Node;
//同时创建两个链表实现堆栈,top实现基本站,min实现最小栈
typedef struct {
Node top;
Node min;
} MinStack;
初始化
MinStack* minStackCreate() {
MinStack* temp = (MinStack*)malloc(sizeof(MinStack));
temp->top = NULL;
temp->min = NULL;
return temp;
}
push
//辅助栈的插入操作
void insertMin(MinStack* obj, int x){
Node temp = obj->min;
Node newMin = (Node)malloc(sizeof(struct node));
if(x <= temp->val){
newMin->val = x;
newMin->next = temp;
obj->min = newMin;
return ;
}
while(temp != NULL){
if(x > temp->val && (temp->next != NULL || x <= temp->val)){
newMin->val = x;
newMin->next = temp->next;
temp->next = newMin;
return ;
}
temp = temp->next;
}
}
//首先进行基本栈的插入,再完成辅助栈的插入
void minStackPush(MinStack* obj, int x) {
//考虑堆栈是空的情况
if(obj->top == NULL && obj->min == NULL){
Node newtop = (Node)malloc(sizeof(struct node));
Node newMin = (Node)malloc(sizeof(struct node));
obj->top = newtop;
obj->min = newMin;
obj->top->val = x;
obj->top->next = NULL;
obj->min->val = x;
obj->min->next = NULL;
}
else{
Node newtop = (Node)malloc(sizeof(struct node));
newtop->val = x;
newtop->next = obj->top;
obj->top = newtop;
insertMin(obj, x);
}
}
pop
//同理先删基本栈再删辅助栈,需要单独排除删除元素在栈顶的情况
void deleMin(MinStack* obj, int x)
{
Node temp = obj->min;
Node lastnode = obj->min;
if(x == obj->min->val){
obj->min = obj->min->next;
free(temp);
return ;
}
while(temp != NULL){
if(x == temp->val){
lastnode->next = temp->next;
free(temp);
return ;
}
lastnode = temp;
temp = temp->next;
}
}
void minStackPop(MinStack* obj) {
if(obj->top == NULL) return;
Node temp = obj->top;
obj->top = obj->top->next;
deleMin(obj, temp->val);
free(temp);
}
getMin and getTop
int minStackTop(MinStack* obj) {
if(obj->top == NULL) return 0;
return obj->top->val;
}
int minStackGetMin(MinStack* obj) {
if(obj->min == NULL) return 0;
return obj->min->val;
}
free
void minStackFree(MinStack* obj) {
Node temp;
while(obj->top)
{
temp = obj->top;
obj->top = obj->top->next;
free(temp);
}
while(obj->min)
{
temp = obj->min;
obj->min = obj->min->next;
free(temp);
}
}
时间复杂度和空间复杂度
- 时间复杂度: 基本栈的是O(1),辅助栈的是O(n),因为辅助栈是需要排序插入的(按道理说这不应该叫栈)
- 空间复杂度O(N): 元素个数,很好理解
总结
可以双向链表进行改进,这样可以不用再插入和删除操作中单独判断元素是否在栈顶的情况,代码可以少很多。