美文网首页
算法设计 --- 最小栈

算法设计 --- 最小栈

作者: _code_x | 来源:发表于2021-07-04 21:53 被阅读0次

算法描述

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

  • push(x) —— 将元素 x 推入栈中。
  • pop() —— 删除栈顶的元素。
  • top() —— 获取栈顶元素。
  • getMin() —— 检索栈中的最小元素。

示例

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
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:辅助栈和数据栈同步

特点:编码简单,不用考虑一些边界情况,就有一点不好:辅助栈可能会存一些“不必要”的元素。

  • 方案2:辅助栈和数据栈不同步

特点:由“辅助栈和数据栈同步”的思想,我们知道,当数据栈进来的数越来越大的时候,我们要在辅助栈顶放置和当前辅助栈顶一样的元素,这样做有点“浪费”。基于这一点,我们做一些“优化”,但是在编码上就要注意一些边界条件。

(1)辅助栈为空的时候,必须放入新进来的数;

(2)新来的数小于或者等于辅助栈栈顶元素的时候,才放入,特别注意这里“等于”要考虑进去,因为出栈的时候,连续的、相等的并且是最小值的元素要同步出栈;

(3)出栈的时候,辅助栈的栈顶元素等于数据栈的栈顶元素,才出栈。

总结一下:出栈时,最小值出栈才同步;入栈时,最小值入栈才同步。

对比:个人觉得“同步栈”的方式更好一些,因为思路清楚,因为所有操作都同步进行,所以调试代码、定位问题也简单。“不同步栈”,虽然减少了一些空间,但是在“出栈”、“入栈”的时候还要做判断,也有性能上的消耗。

代码实现

  • 方案1:同步压入
class MinStack {

    private Stack<Integer> stackData;
    private Stack<Integer> stackMin;

    public MinStack() {
        stackData = new Stack<>();
        stackMin = new Stack<>();
    }
    
    public void push(int val) {
        stackData.push(val);
        if (stackMin.isEmpty() || val < stackMin.peek()) {
            stackMin.push(val);
        } else {
            stackMin.push(stackMin.peek());
        }
    }
    
    public void pop() {
        if (!stackData.isEmpty()) {
            stackData.pop();
            stackMin.pop();
        }
    }
    
    public int top() {
        if (!stackData.isEmpty()) {
            return stackData.peek();
        }
        throw new RuntimeException("your stack is empty!");
    }
    
    public int getMin() {
        if (!stackMin.isEmpty()) {
            return stackMin.peek();
        }
        throw new RuntimeException("your stack is empty!");
    }
}
  • 方案2:不同步压入
class MinStack {

    private Stack<Integer> stackData;
    private Stack<Integer> stackMin;

    public MinStack() {
        stackData = new Stack<>();
        stackMin = new Stack<>();
    }
    
    public void push(int val) {
        // 将必要的元素加入最小栈
        if (stackMin.isEmpty() || val <= stackMin.peek()) {
            stackMin.push(val);
        } 
        stackData.push(val);
    }
    
    public void pop() {
        // 数据栈中的元素必须删除
        if (!stackData.isEmpty()) {
            int val = stackData.pop();
            // 自动拆箱比较
            if (val == stackMin.peek()) {
                stackMin.pop();
            }
        }
    }
    
    public int top() {
        if (!stackData.isEmpty()) {
            return stackData.peek();
        }
        throw new RuntimeException("your stack is empty!");
    }
    
    public int getMin() {
        if (!stackMin.isEmpty()) {
            return stackMin.peek();
        }
        throw new RuntimeException("your stack is empty!");
    }
}

总结与补充

  • 上述两种方案都是使用一个辅助栈保存数据栈每一步对应的最小值。所有操作时间复杂度O(1),空间复杂度O(n)。
  • 两种方案的不同点:
    • 入栈,当前值大于最小栈栈顶时:方案1:同步压入最小栈的栈顶;方案2:不压入元素(节省空间)
    • 出栈,方案1:同步出栈;方案2:当数据栈顶元素等于最小栈栈顶元素则,最小栈出栈,否则最小栈不出栈。为什么呢?这要看我们的压入规则了,最小栈栈顶一定不会出现小于数据栈的情况,只可能大于或者等于。所以当等于时,我们弹出最小栈栈顶元素,大于时,不弹出最小栈栈顶元素。

巨人的肩膀

https://leetcode-cn.com/problems/min-stack/solution/shi-yong-fu-zhu-zhan-tong-bu-he-bu-tong-bu-python-/

相关文章

  • 算法设计 --- 最小栈

    算法描述 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 push(x) ...

  • 栈系列之-获取最小值

    一、栈获取最小值算法概述 获取栈的最小值算法:可以动态的获取一个栈中元素的最小值,动态的意思是,当该栈发生push...

  • 初级算法-设计问题-最小栈

    设计一个支持push、pop、top 操作,并能在常数时间内检索到最小元素的栈. push(x) ------ 将...

  • LeetCode初级算法--设计问题02:最小栈

    LeetCode初级算法--设计问题02:最小栈 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小...

  • 每日Leetcode—算法(14)

    141.环形链表 算法(快慢指针): 155.最小栈 算法一: 算法二: 167. 两数之和 II - 输入有序数...

  • LeetCode:最小栈

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

  • 5、数据结构

    1、最小栈—* 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。push(x) ...

  • 算法 1.3.1 最小栈 【leetcode 155】

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

  • 数据结构——栈和队列

    用数组实现栈和队列 用栈实现队列 用队列实现栈 栈和队列的经典算法题最小间距栈宠物收养所 数组实现栈和队列 用数组...

  • Swift 最小栈 - LeetCode

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

网友评论

      本文标题:算法设计 --- 最小栈

      本文链接:https://www.haomeiwen.com/subject/zipvultx.html