请设计一个栈,除了常规栈支持的pop与push函数以外,还支持min函数,该函数返回栈元素中的最小值。执行push,pop和min操作的时间复杂度必须为O(1)
示例:
MinStack minStack=new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); 返回-3
minStack.pop();
minStack.top(); 返回0;
minStack.getMin(); 返回-2
1‘、使用辅助类解决
定义一个链表如下:
class ListNode{
public inr val;
public int min;
public ListNode next;
public ListNode(int val,int min,ListNode next){
this.val=val;
this.min=min;
this.next=next;
}
}
对链表的操作永远都是链表的头,假如在栈中加入3-2-5-4
整体代码:
class MinStack{
//链表头,相当与栈顶
private ListNode head;
//判断栈是否为空
private boolean empty(){
return head==null;
}
//压栈,需要判断栈是否为空
public void push(int x){
if(empty()){
head=new ListNode(x,x,null);
}else{
head=new ListNode(x,Math.min(x,head.min),head);
}
}
//出栈,相当于把链表头删除
public void pop(){
if(empty()){
throw new IllegalStateException("栈为空....");
}
return head.val;
}
//链表中头结点保存的是整个链表最小的值,所以返回head.min也就是返回栈中最小的值
public int min(){
if(empty()){
throw new IllegalStateException("栈为空.....");
}
return head.min;
}
}
class ListNode{
public int val;
public int min;
public ListNode next;
public ListNode(int val,int min,ListNode next){
this.val=val;
this.min=min;
this.next=next;
}
}
上面解决方式是使用一个辅助的类,实际上如果使用辅助类,我们也可以使用官方提供的栈
class StackNode{
public int val;
public int min;
public StackNode(int val,int min){
this.val=val;
this.min=min;
}
}
class MinStack{
private Stack<StackNode> stack=new Stack<>();
//判空
public boolean empty(){
return stack.isEmpty();
}
//压栈
public void push(int x){
if(empty()){
stack.push(new StackNode(x,x));
}else{
stack.push(new StackNode(x,getMin()));
}
}
//出栈
public void pop(){
if(empty()){
throw new IllegalStateException("栈为空....");
}
}
//显示栈顶值
public int top(){
if(empty()){
throw new IllegalStateException("栈为空....");
}
return stack.peek().val;
}
//最小值
public int getMin(){
if(empty()){
throw new IllegalStateException("栈为空.....");
}
return stack.peek().min;
}
}
维护两个栈,一个是主栈,一个是最小栈
1、每次push操作将元素插入主栈栈顶时,同时判断是否小于等于最小栈点的栈顶元素,如果是则插入最小栈
2、每次pop操作,主栈栈顶元素如果等于最小栈栈顶元素,则同步出栈
3、min操作则返回最小栈的top值
因为主栈的第一个元素一定插入最小栈,所以不用担心最小栈为空的情况
class MinStack{
private Stack<Integer> stack;
private Stack<Integer> minRecord;
public MinStack(){
this.stack=new Stack();
this.minRecord=new Stack();
}
public void push(int x){
stack.push(x);
if(minRecord.isEmpty() || minRecord.peek()>=x){
minRecord.push(x);
}
}
public void pop(){
int res=stack.pop();
if(minRecord.peek()>=res){
minRecord.pop();
}
}
public int top(){
return stack.peek();
}
public int getMin(){
return minRecord.peek();
}
}