设计最小栈,即有栈的基本操作push,pop,peek,还有返回栈中最小值的功能getMin
提示:之前我们说系统栈就正常push,pop和peek
现在需要设计一个最小栈,o(1)速度返回当前栈中的最小值。
文章目录
题目
设计最小栈,即有栈的基本操作push,pop,peek,
还有一个新函数,即:返回当前栈中的最小值的getMin()
一、审题
示例:比如压入2 3 1 4 5
对应的栈中最小值应该是:
2 2 1 1 1
请实现这样的栈:最小栈
二、最小栈的设计方法
实际上,最小栈,根据示例也能看出来,也就是2个系统栈:数据栈data和最小值栈min
data负责日常push,pop和peek功能
每次push时,需要对比此时新来的value和min中栈顶那个值的大小
如果:
(1)value>=min栈顶那个值:则需要把min栈顶赋值给value,存入min,代表最小值已然不变
(2)value<min栈顶那个值:则确实来了一个新的最小值,直接将value存入min即可,代表新的最小值来了
这样的话,data自然干自己的
min保证数量和data一样,而且,data目前这范围内最小值,都在min放好的,不会乱
看上图就明白
当data中只有2,此时min必然也是只有2,它就是最小值
当data中有32,此时最小值自然也是2,
当data中有132,来了一个1比2小,自然1从今往后就是最小值
之后来的数大于等于1,min中栈顶也自然存1
除非来了个0,或者更小的,那就是让min再放更小的
(3)弹出的时候,data自己常规骚操作,然后min也要跟着弹出一个,保证范围内数量跟data一致;
手撕代码:
//复习最小栈,很简单,就是另外拿一个系统栈,放每次输入的最小值,即可
public static class MinStack{
//俩系统栈
public Stack<Integer> dataStack;
public Stack<Integer> minStack;
public MinStack(){
dataStack = new Stack<>();
minStack = new Stack<>();
}
//isEmpty
public boolean isEmpty(){
return dataStack.isEmpty();
}
//push
public void push(int value){
//data正常玩自己的
dataStack.push(value);
//关键在这,判断新来的value,和minStack的栈顶,啥情况
if (minStack.isEmpty()) minStack.push(value);//第一个来的数,必然就是它最小了
else if (value >= minStack.peek()) {
value = minStack.peek();//重新赋值给value,然后加入min,别忘了哦
minStack.push(value);
}
else minStack.push(value);//如果跳过上面那些if,说明更小的来了
}
//pop
public int pop(){
//没有了报错
if (dataStack.isEmpty()) throw new RuntimeException("没得数!");
//min要和data数量一致,范围一致,所以要先弹出一个
minStack.pop();
return dataStack.pop();
}
//peek
public int peek(){
//没有就报错
if (dataStack.isEmpty()) throw new RuntimeException("没得数!");
//有就看栈顶,与min无关
return dataStack.peek();
}
//关键函数来了,getMin
public int getMin(){
//没有元素,报错
if (minStack.isEmpty()) throw new RuntimeException("没得数!");
//有的话,自然,就返回minStack的栈顶,与data无关
return minStack.peek();
}
}
public static void test2(){
MinStack stack = new MinStack();
stack.push(2);
System.out.println("当前最小值:"+ stack.getMin());//2
stack.push(3);
System.out.println("当前最小值:"+ stack.getMin());//2
stack.push(1);
System.out.println("当前最小值:"+ stack.getMin());//1
stack.push(4);
System.out.println("当前最小值:"+ stack.getMin());//1
stack.push(5);
System.out.println("当前最小值:"+ stack.getMin());//1
System.out.println("栈顶数据:"+ stack.peek());//5
System.out.println(stack.isEmpty());
System.out.println(stack.pop());//5
System.out.println("当前最小值:"+ stack.getMin());//1
System.out.println(stack.pop());//4
System.out.println("当前最小值:"+ stack.getMin());//1
System.out.println(stack.pop());//1
System.out.println("当前最小值:"+ stack.getMin());//2
System.out.println(stack.pop());//3
System.out.println("当前最小值:"+ stack.getMin());//2
System.out.println(stack.pop());//2
System.out.println(stack.isEmpty());
}
public static void main(String[] args) {
// test();
test2();
}
看看结果,很完美:
当前最小值:2
当前最小值:2
当前最小值:1
当前最小值:1
当前最小值:1
栈顶数据:5
false
5
当前最小值:1
4
当前最小值:1
1
当前最小值:2
3
当前最小值:2
2
true
总结
提示:重要经验:
1)最小栈,无非就是多了一个存最小值的栈,换成最大栈的话,估计也是很简单的
2)用底层的系统数据结构,实现新的的你想要的数据结构,这就是学习数据结构与算法的意义,这是大厂未来要招聘你进入优化算法和实现新的业务功能的本质。