【左程云算法09】栈的入门题目-最小栈

目录

栈的入门题目-最小栈

代码演示


视频链接

算法讲解015【入门】栈的入门题目-最小栈

Leecode155

栈的入门题目-最小栈

实现一个getmin方法(高效方法,即不用遍历),希望能实现O(1)

做法:准备两个栈

data和min栈

当我压入3时,我同步压入。如果再加入个5,data栈压入5。让最小栈的栈顶和要压入的数比较。3<5,所以min栈再压入5。

比如再压入2,2现在是最小的,所以左右同时压入2。

比如再压入7,2目前还是最小的,所以左边压入7,右边压入2。

总结:就这三条逻辑1)当前压的数字<=min栈的顶,当前数字压入min栈

2)当前压得数字>min栈的顶,min原来的数压入min栈

3)min栈为空,data为空,当前要压的数字压入min栈

为什么要这么做?

保证一一对应。即永远右边的栈顶是栈里元素的最小值。

要弹出的时候,data栈和min栈同步弹出就行

代码演示

import java.util.Stack;
public class MinStack1 {
    //data栈:用于存放所有实际的数字
    public Stack<Integer>data;
    //min栈:辅助栈,其栈顶永远是当前data栈中的最小值
    public Stack<Integer>min;
    //构造方法:
    public MinStack1(){
        //初始化两个栈
        data = new Stack<Integer>();
        min = new Stack<Integer>();
    }
    /**
     * 将一个元素推入栈中
     */
    public void push(int val){
        //第一步:无论如何,新元素val总是要被推入data栈
        data.push(val);
        //第二步:根据规则决定往min栈中推入什么
        //条件一:min栈为空?(即这是第一个元素,它当然是最小值)
        //条件二:val<=min.peek()? 如果是的话,那么目前val最小,val压入到min栈中。
        //条件一条件二都是将val直接压入min栈中
        if(min.isEmpty()||val<=min.peek()){
            min.push(val);
        }else{
            //如果是条件三:即min.peek比val要小,那么再把它压一遍
            min.push(min.peek());
        }
    }
    /**
     * 从栈中弹出一个元素
     */
    public void pop(){
        //data栈和min栈是严格同步的,所以data栈弹出时min栈也应该弹出,以维持同步
        data.pop();
        min.pop();
    }
    /**
     * 查看栈顶元素
     */
    public int top(){
        //栈顶元素就是data栈的栈顶
        return data.peek();
    }
    /**
     * 获取栈的最小元素
     */
    public int getMin() {
        //即min的peek
        return min.peek();
    }
}

但这种方法(即用java自带的stack类效率低),所以我们选择用数组来亲手搭建一个栈,这样效率高。

public class MinStack2 {
    //假设这个栈最多装8001个元素
    public final int MAXN = 8001;
    //用两个整型数组来代替stack类
    public int[]data;//对应之前的data栈
    public int[]min;//对应之前的min栈
    //变量size:即表示当前元素的数量,也指向下一个要插入的位置
    int size;

    //构造方法
    public MinStack2(){
        //创建两个刚好能容纳MAXN个整数的数组
        //相当于建好了两怕空的储物柜
        data = new int[MAXN];
        min = new int[MAXN ];
        //初始时一个元素都没有所以size是0
        size = 0;
    }
    /**
     * 将一个元素推入我们用数组模拟的栈中
     */
    public void push(int val){
        //data[size] = val
        //把新元素val放入data数组的第size个位置
        //如果size是0,就放在data[0];如果size是1,就放在data[1]
        data[size] = val;

        //data栈压入之后,我们来想一想min栈怎么办(和上一题一样)
        if(size == 0||val<=min[size-1]){
            min[size] = val;
        }else{
            //否则,最小值不变
            //复制上一个位置的最小值到当前位置,以保持和data数组的同步
            min[size] = min[size-1];
        }
        //最重要的一步:把size加1,让指针指向下一个空位
        //并且表示元素总数增加一个
        size++;
    }
    /**
     * 从我们用数组模拟的栈中弹出一个元素
     */
    public void pop(){
        //我们不需要真的去清除数组里的data[size-1]
        //只需要把size减1,就等于我们逻辑上抛弃了最后一个元素
        //下次push时,那个位置的值会被自然地覆盖掉
        size--;
    }
    /**
     * 查看栈顶元素
     */
    public int top(){
        //因为size指向地是下一个空位,所以栈真正地顶部元素位于它地前一个位置
        // 即size-1
        return data[size-1];
    }
    /**
     * 获取栈中的最小元素
     */
    public int getMin(){
        //同理,最小元素即min数组的栈顶位置,也就是size-1
        return min[size-1];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值