求最小栈

235 阅读4分钟

题目描述

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) -- 将元素 x 推入栈中。
  • pop() -- 删除栈顶的元素。
  • top() -- 获取栈顶元素。
  • getMin() -- 检索栈中的最小元素。

菜鸡(我的思路)

不就是简单实现一个栈,在通过依次比较不就得到最小值嘛,于是我就这样做了

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 800

typedef struct {
    int *data;
    int top;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() {
    MinStack *obj=(MinStack *)malloc(sizeof(MinStack));
    obj->data=(int *)malloc(MAXSIZE*sizeof(int));
    obj->top=-1;
    return obj;
}

void minStackPush(MinStack* obj, int x) {
  if(obj->top==MAXSIZE-1){
      
  }else{
      obj->top++;
      obj->data[obj->top]=x;
  }
}

void minStackPop(MinStack* obj) {
  if(obj->top==-1){
      
  }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;
}

void minStackFree(MinStack* obj) {
    free(obj->data);
    obj->data=NULL;
    free(obj);
    obj=NULL;
}

int main(){
	MinStack *s=minStackCreate();
	minStackPush(s,-2);
	minStackPush(s,0);
	minStackPush(s,-3);
	printf("%d\n",minStackGetMin(s));
	minStackPop(s);
	printf("%d\n",minStackTop(s));
	printf("%d\n",minStackGetMin(s));
	return 0;
}

渺小的我观看了大神答案

大神结题

“以空间换时间”,使用辅助栈是常见的做法 理解就是在创建一个栈用于存放最小值,但辅助栈也分为两种

  • 同步
    思路: 当将元素进栈时,辅助栈也同样添加元素(为第一个就直接添加,不为第一个时,就进行比较,若添加的元素大于辅助栈的栈顶元素,就添加最小元素,小于就添加本来的元素) 复杂度为O(n)

自己写的C语言版本

typedef struct {
	int *data;
	int *helper;
	int top;
}MinStack;

MinStack* minStackCreate(){
	MinStack *s=(MinStack *)malloc(sizeof(MinStack));
	s->data=(int *)malloc(sizeof(int)*MAXSIZE);
	s->helper=(int *)malloc(sizeof(int)*MAXSIZE);
	s->top=0;
	return s;
}

void minStackPop(MinStack* obj) {
  if(obj->top==0){
      
  }else{
      obj->top--;
      obj->helper[obj->top]=obj->data[obj->top]=NULL;
  }
}
void minStackPush(MinStack* obj, int x){
	if(obj->top==MAXSIZE){
		
	}else{
		if(obj->top==0 || x<obj->helper[obj->top-1]){
			obj->helper[obj->top]=x;
		}else{
			obj->helper[obj->top]=obj->helper[obj->top-1];
		}
		obj->data[obj->top++]=x;
	}
}

int minStackTop(MinStack* obj) {
  if(obj->top==0){
      return 0;
  }
  return obj->data[obj->top-1];
  
}

int minStackGetMin(MinStack* obj) {
  if(obj->top==0) {
  	return 0;
  }else{
  	return obj->helper[obj->top-1];
  }
  
}

void minStackFree(MinStack* obj) {
    free(obj->data);
    free(obj->helper);
    obj->data=NULL;
    obj->helper=NULL;
    free(obj);
    obj=NULL;
}

大神的原码:使用Python实现,看着就简单

作者:liweiwei1419 链接:leetcode-cn.com/problems/mi…

class MinStack:

    # 辅助栈和数据栈同步
    # 思路简单不容易出错

    def __init__(self):
        # 数据栈
        self.data = []
        # 辅助栈
        self.helper = []

    def push(self, x):
        self.data.append(x)
        if len(self.helper) == 0 or x <= self.helper[-1]:
            self.helper.append(x)
        else:
            self.helper.append(self.helper[-1])

    def pop(self):
        if self.data:
            self.helper.pop()
            return self.data.pop()

    def top(self):
        if self.data:
            return self.data[-1]

    def getMin(self):
        if self.helper:
            return self.helper[-1]
  • 不同步: 思路与之前的有一丢丢不同,对第一种的改进,减少空间浪费 注意点
    • 1:辅助栈的元素空的时候,必须放入新进来的数
    • 2:新来的数小于或者等于辅助栈栈顶元素的时候,才放入(特别注意这里等于要考虑进去) 原因就是:如果取消等于这个条件,当pop掉这个元素时,本应该没有这个元素了,但你的最小栈里还保留着,很可能冲突
    • 3:出栈的时候,辅助栈的栈顶元素等于数据栈的栈顶元素,才出栈,即"出栈保持同步"就可以了

另一种思路

只利用一个栈,每一次执行push操作时,进行两次入栈,第一次入栈此元素,第二次入栈此时栈中最小的元素;执行pop操作与之相对:将剩余元素遍历一遍,找到最小值,并push到栈中

复杂度: O(n)

typedef struct {
    int *data;
    int top;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() {
    MinStack *obj=(MinStack *)malloc(sizeof(MinStack));
    obj->data=(int *)malloc(MAXSIZE*sizeof(int));
    obj->top=-1;
    return obj;
}

void minStackPush(MinStack* obj, int x) {
  if(obj->top==MAXSIZE-1){
      
  }else if(obj->top==-1){
      obj->top++;
      obj->data[obj->top]=x;
      obj->top++;
      obj->data[obj->top]=x;
  }else{
      int tmp=obj->data[obj->top];
      obj->top++;
      obj->data[obj->top]=x;
      if(tmp<x){
        obj->top++;
        obj->data[obj->top]=tmp;
      }else{
        obj->top++;
        obj->data[obj->top]=x;
      }
  }
}

void minStackPop(MinStack* obj) {
  if(obj->top==-1){
      
  }else{
      obj->top--;
      obj->top--;
      int i;
      int min=obj->data[0];
      for(i=1;i<obj->top-1;i++){
          if(obj->data[i]<min){
              min=obj->data[i];
          }
      }
      obj->data[obj->top]=min;
  }
}

int minStackTop(MinStack* obj) {
  if(obj->top==-1){
      return 0;
  }
  return obj->data[obj->top-1];
  
}

int minStackGetMin(MinStack* obj) {
  return obj->data[obj->top];
}

void minStackFree(MinStack* obj) {
    free(obj->data);
    obj->data=NULL;
    free(obj);
    obj=NULL;
}

总结

学习算法要敢于想象,从多种方向思考