包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof

起初我只考虑到了只要调用min函数,就可以知道栈中的最小元素,并且时间复杂度是O(1),那么只要保证最小值在栈顶就好了,然后我居然借助一个辅助栈实现栈的出栈序列是一个升序序列。虽然可以实现栈顶元素是最小值,但是最后提交的时候发现是错误的,因为它的题目要求是出栈序列是基于入栈的时候,如果将栈进行排序的话,那么出栈序列就没有办法达到要求

正确的思路:
定义两个栈,其中一个栈stack用于正常的入栈、出栈操作,另一个栈stack2是用于存放最小值。

①在执行push操作的时候,stack直接入栈,但是stack2需要进行一定的条件判断,如果当前插入的元素x小于等于stack2的栈顶元素,或者当前的stack2是空的,那么直接将x压入栈stack2中。

②进行pop的操作的时候,stack直接调用pop方法,将栈stack中的栈顶元素出栈,并将这个栈顶元素赋值给y,然后我们判断y是否等于stack2中的栈顶元素,如果相等,那么我们需要将stack2中的栈顶元素跳出。为什么y等于stack2的栈顶元素的时候,需要从stack2跳出栈顶元素咧?因为执行y == stack2.peek(),主要是想判断当前从stack中跳出的元素是否为最小值,如果是最小值,那么我们就需要同时从stack2中跳出,从而保证栈的最小值不再是y了。

③执行top操作的时候,是基于入栈操作进行的,所以stack调用peek方法。
④执行min操作的时候,那么stack2调用peek方法即可。因为stack2的栈顶元素就是栈的最小值。

对应的代码:

import java.util.Stack;
class MinStack {
    Stack<Integer> stack ;//定义一个栈,最后出栈序列是一个升序序列
    Stack<Integer> stack2;//用于存放临时的栈顶元素
    /** initialize your data structure here. */
    public MinStack() {
       stack = new Stack<Integer>();
       stack2 = new Stack<Integer>();
    }
    public void push(int x) {
       if(stack2.empty() || stack2.peek() >= x){
           //如果stack2为空,或者小于等于stack2中的栈顶元素,那么就将x压入stack2中
           stack2.add(x);
       }
       stack.add(x);
    }
    
    public void pop() {
        int x = stack.pop();
        if(x == stack2.peek()){
        /*
        如果从栈stack中跳出的元素同样等于stack2的栈顶元素,那么我们将这个
        元素从stack2中跳出,因为stack中的最小值不在是x了,为了保证一致性,所
        以需要stack2中同时需要跳出x
        */
            stack2.pop();
        }
    }
    
    public int top() {
       return stack.peek();//由于是基于入栈时的先后顺序的,所以这里是stack调用peek方法
    }
    
    public int min() {
        return stack2.peek();//stack2是存放最小值,并且栈顶元素是最小值,所以是返回stack2的栈顶元素
    }


}
/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.min();
 */

运行结果
在这里插入图片描述

为了更好的理解stack2的作用,我们在执行push操作的时候可以是这样子操作:
如果stack2是空的或者新插入的元素x小于等于stack2的栈顶元素,那么就将x压入栈stack2中,否则就再次将栈顶元素压入stack2。

这样操作的话,相应的,在执行pop操作的时候,就不再需要向上面那样了,将x和stack2的栈顶元素进行比较,判断是否相等了,直接将stack2的栈顶元素跳出。

看起来好像不太懂?请看下面的分析:
在这里插入图片描述

对应的代码:

import java.util.Stack;
class MinStack {
    Stack<Integer> stack ;//定义一个栈,存放入栈序列
    Stack<Integer> stack2;//用于存放最小值,并且最小值在栈顶中
    /** initialize your data structure here. */
    public MinStack() {
       stack = new Stack<Integer>();
       stack2 = new Stack<Integer>();
    }
    public void push(int x) {
       stack.add(x);//stack直接入栈
       /*
       如果stack2为空,或者stack2的栈顶元素大于等于x,那么x压入stack2中,
       否则,stack2的栈顶元素小于x,那么就再次将stack2的栈顶元素压入
       stack2中,保证了两个栈的长度相同,同时保证了最小值没有发生改变
       */
       if(stack2.empty()){
           stack2.add(x);
       }else{
           if(stack2.peek() >= x)
              stack2.add(x);
            else
              stack2.add(stack2.peek());
       }
       
    }
    
    public void pop() {
    /*
    两个栈同时进行pop操作,不仅可以保证两个栈的长度相等,同时保证了最小值
    的更新
    */
        stack.pop();
        stack2.pop();
    }
    
    public int top() {
       return stack.peek();
    }
    
    public int min() {
        return stack2.peek();
    }


}
/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.min();
 */

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值