题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。
首先读懂题目,需要保留所有栈的特性(先进后出),并且该栈中有能够提供找到最小元素的min函数。普通的栈是无法实现的。说白了就是让你设计一个栈,其中有一个函数时可以返回最小值的。显然这个栈不是让你写从零写起,你可以依托于包中的栈的普通方法,而把焦点在如何实现min函数
不能用一个变量记录最小值,因为当最小值弹栈后,该变量就得变成新的最小值,这个不容易实现。所以需要定义一个辅助的数据结构,可以记录多个变量,可以随着原来的栈的弹出压入而更新对应的最小值。
第一想法是使用最小堆,但是最小堆还需要实现。既然本身可以依托于包中的栈,那么比较讨巧的做法就是用一个辅助栈。
因此需要设计辅助栈的压入规则和弹出规则:
写法1:
用一个栈data保存数据,用另外一个栈min保存依次入栈最小的数
比如,data中依次入栈,5, 4, 3, 8, 10, 11, 12, 1
则min依次入栈,5, 4, 3,3, 3, 3, 3, 1
每次入栈的时候,如果入栈的元素比min中的栈顶元素小或等于则两边都入栈,否则辅助栈压入一个当前的最小值。这样可以保证两个栈的入栈的数量是一致的。
import java.util.Stack; public class Solution { Stack<Integer> stack_data=new Stack<Integer>();//原来的栈 Stack<Integer> stack_min=new Stack<Integer>();//辅助栈 public void push(int node) { stack_data.push(node);//原来的栈肯定要入的 if(stack_min.empty() || stack_min.peek()>node) {//为空就使用不了peek stack_min.push(node);//当前数更小则当前数入栈 }else { stack_min.push(stack_min.peek());//否则压入辅助栈的最小值 } } public void pop() { if(!stack_data.empty()) {//同时弹 stack_data.pop(); stack_min.pop(); } } public int top() {//返回原栈的栈顶元素 return stack_data.peek(); } public int min() {//返回辅助栈的栈顶元素 return stack_min.peek(); } }
写法2
用一个栈data保存数据,用另外一个栈min保存依次入栈最小的数
比如,data中依次入栈,5, 4, 3, 8, 10, 11, 12, 1
则min依次入栈,5, 4, 3,null, null, null, null, 1
null就是不入栈。也就是只有出现最小值时,辅助栈才会入栈。而弹出时,原栈和辅助栈的栈顶相同时,辅助栈才会弹栈。
import java.util.Stack; public class Solution { Stack<Integer> stack_data=new Stack<Integer>(); Stack<Integer> stack_min=new Stack<Integer>(); public void push(int node) { stack_data.push(node);//反正原栈肯定要入的 if(stack_min.empty() || stack_min.peek()>node) { //出现较小值才入栈,否则不操作 stack_min.push(node); } } public void pop() { if(!stack_data.empty()) {//首先判断不为空 if(stack_data.peek() != stack_min.peek()) //不相等,说明弹出的不是当前最小值,原栈弹出就可以 stack_data.pop(); else{//是最小值,两个栈一起弹 stack_data.pop(); stack_min.pop(); } } } public int top() { return stack_data.peek(); } public int min() { return stack_min.peek(); } }
总结:其实很多算法题考点不同,本题的考点在于如何实现Min函数,因此不需要考虑太多栈的设计考察一个栈如何设计,并不是说栈的设计不重要,只是本题的侧重点不在与栈的设计,有些大佬功底比较厚,考虑的也比较多,这也正常。非大佬就把握好考点就好啦。
附上左神的一张图,构造函数都搞出来了,把一些思想用进来就很强势。还有些大佬在回答中进行扩容的,是真的强。
说明:这个和写法2的原理相同