剑指offer之面试题21:包含min函数的栈

题目描述

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

思路:
第一种思路,可不可以每次push操作后,对栈中元素排序,使最小的元素位于栈顶?这样min操作可以保证在O(1)内完成,但pop操作就与栈的pop操作违背了(栈顶的元素不一定是最后进栈的,不是后进先出)。显然这种思路行不通,直接pass掉。

第二种思路,可不可以用一个临时值保存min?如果最小元素pop出栈了,如何求当前栈中的min(原来的次最小元素)。顺着这种思路,是否可以使用数组来保存最小元素、次最小元素、…,可行,但比较复杂,因为数组对于增删维护不太方便(比如,你用数组下标来标识,0存放最小,那如果pop或push改变了栈中最小元素,都要移动数组元素,虽然找到minO(1),但维护O(n))。最终你会发现,用辅助栈来存放最小元素,满足题意要求。举个例子:向空的数据栈中压入3,此时栈中最小元素就是3,把3同时压入辅助栈。然后压入4,4>3,此时最小元素3,把3压入辅助栈。然后再压入2,2<3,此时最小元素2,把2压入辅助栈。再压入1,1<2,此时最小元素1,把1压入辅助栈。绘制如下表格:

步骤操作数据栈辅助栈最小值
1压入3333
2压入43,43,33
3压入23,4,23,3,22
4压入13,4,2,13,3,2,11
5弹出3,4,23,3,22
6弹出3,43,33
7压入03,4,03,3,00

总结出方法:数据栈push元素时,与栈中最小元素比较(minStack.top()),并将比较后的最小元素push进辅助栈。当数据栈pop元素时,辅助栈也pop元素,更新最小元素。

写出代码:

import java.util.Stack;

public class Solution {
    public static Stack<Integer> dataStack=new Stack<Integer>();
    public static Stack<Integer> minStack=new Stack<Integer>();
    public static void push(int node) {
        dataStack.push(node);
        if(dataStack.size()==0||node<top()){
            minStack.push(node);
        }
        else{
            minStack.push(top());
        }
    }

    public static void pop() {
        if(dataStack.size()>0&&minStack.size()>0){
            dataStack.pop();
            minStack.pop();
        }
    }

    public static int top() {
        if(minStack.size()>0){
            return minStack.peek();
        }
        if(dataStack.size()>0){
            return dataStack.peek();
        }
        return -1;     
    }

    public static int min() {
        return top();
    }
    public static void main(String[] args){
        push(3);
        push(4);
        push(2);
        push(1);
        System.out.println(min());
        pop();
        System.out.println(min());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值