LC 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) —— 将元素 x 推入栈中。
  • pop() —— 删除栈顶的元素。
  • top() —— 获取栈顶元素。
  • getMin() —— 检索栈中的最小元素。
    在这里插入图片描述

方法一:使用辅助堆栈

思路:

  • 借用一个辅助栈 因为TS中没有栈,所以用数组代替,用于存获取stack中最小值。
  • push()方法: 每当push()新值进来时,如果 小于等于 helpArr 栈顶值,则一起push()到 helpArr,即更新了栈顶最小值;
  • ()方法: 判断将pop()出去的元素值是否是min_stack栈顶元素值(即最小值),如果是则将 helpArr栈顶元素一起pop(),这样可以保证 helpArr 栈顶元素始终是stack中的最小值。
  • getMin()方法: 返回 helpArr 栈顶即可。
  • helpArr 等价于遍历stack所有元素,把升序的数字都删除掉,留下一个从栈底到栈顶降序的栈。
  • 相当于给stack中的降序元素做了标记,每当pop()这些降序元素,helpArr 会将相应的栈顶元素pop()出去,保证其栈顶元素始终是stack中的最小元素。
  • 复杂度分析:
    (1)时间复杂度 O(1)O(1) :压栈,出栈,获取最小值的时间复杂度都为 O(1)O(1) 。
    (2)空间复杂度 O(N)O(N) :包含 N、N 个元素辅助栈占用线性大小的额外空间。
class MinStack {
    constructor() {
        this.stackArr = [];
        this.helpArr = [];
    }

    protected stackArr: number[];
    protected helpArr: number[];

    push(val: number): void {
        this.stackArr.push(val);
        if(!this.helpArr.length) {
            this.helpArr.push(val);
        } else {
            let lastMinNum = this.helpArr[this.helpArr.length-1];
            if(val >= lastMinNum) {
                this.helpArr.push(this.helpArr[this.helpArr.length-1]);
            } else {
                this.helpArr.push(val);
            }
        }
    }

    pop(): void {
        if(this.stackArr.length) {
            this.stackArr.pop();
        }
        if(this.helpArr.length) {
            this.helpArr.pop();
        }
    }

    top(): number {
        if(this.stackArr.length) {
            return this.stackArr[this.stackArr.length-1];
        } else {
            return null;
        }
    }

    getMin(): number {
        if(this.helpArr.length) {
            return this.helpArr[this.helpArr.length-1];
        }
        else { 
            return null;
        }
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * var obj = new MinStack()
 * obj.push(val)
 * obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.getMin()
 */

在这里插入图片描述

方法二:使用一个堆栈实现

经过之后的查阅资料等得知,还有一种可以仅仅使用一个堆栈即可实现的方法(也就是空间复杂度)

思路:

  • 栈中压入的是需要压栈的值和最小值的差值
class MinStack {
    constructor() {
        this.stackArr = [];
        this.min = 9999;
    }

    protected stackArr: number[];
    protected min: number;

    push(val: number): void {
        if (!this.stackArr.length) {
        	//因为最开始栈内是空的所以最小值就是 val ,入栈为 0
            this.stackArr.push(0);
            this.min = val;
        } else {
            //入栈的值和最小值的差值
            this.stackArr.push(val - this.min);
            if (val < this.min)
                this.min = val;
        }
    }

    pop() {
        if (!this.stackArr.length) 
            return;
        let pop = this.stackArr.pop();
        //因为入栈的是差值,当出栈的为负数的时候,说明栈中最小值已经出栈了,
        //这里要重新更新最小值
        if (pop < 0)
            this.min -= pop;
    }

    top(): number {
        let top = this.stackArr[this.stackArr.length-1];
        if (top > 0) {
            //栈顶元素如果是正的,说明栈顶元素压栈的时候是比栈中最小值大的,根据
            //top=x - min,可以计算x=top+min
            return top + this.min;
        } else {
            //当栈顶元素是负数的时候,说明栈顶元素压栈的时候是比栈中最小值小的,
            //而压栈完之后他会更新最小值min,所以如果在使用上面公式肯定是不行
            //的。如果栈顶元素压栈的时候比最小值小,他会更新最小值,这个最小值
            //就是我们要压栈的值,所以这里直接返回min就行了。
            return this.min;
        }
    }

    getMin(): number {
        return this.min;
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * var obj = new MinStack()
 * obj.push(val)
 * obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.getMin()
 */lse { 
            return null;
        }
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * var obj = new MinStack()
 * obj.push(val)
 * obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.getMin()
 */

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值