秋招-算法-最小栈

84 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情 >>

一、题目 LeetCode - 155

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

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int 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.

二、解题思路

本题要求自行实现一个最小栈数据结构,并支持push,pop,top操作。可以考虑对编程语言提供的原生栈实现进行包装、改造,使其可以在常数时间内检索到最小元素。具体做法如下:

  • 首先创建一个栈结构用于存储push的数据,命名为stack;
  • 再另外使用一个栈,用于存储当前push入栈的最小元素,命名为minStack,要注意这个栈的入栈规则为:
    • 若当前push入stack栈的元素小于minStack栈的栈顶元素,则将当前元素push入minStack;
    • 若当前push入stack栈的元素大于或等于minStack栈的栈顶元素,则将minStack栈的栈顶元素再次push入minStack;
  • 当执行pop命令时,不仅需要对stack弾栈,也要对minStack弾栈,这样就可以保证minStack的栈顶元素是当前入栈元素中最小的元素,并且可以达到常数时间检索。

代码

class MinStack {

    private Stack<Integer> stack;
    private Stack<Integer> minStack;

    public MinStack() {
        this.stack = new Stack<>();
        this.minStack = new Stack<>();
        minStack.push(Integer.MAX_VALUE);
    }

    public void push(int val) {
        stack.push(val);
        if (val < minStack.peek()){
            minStack.push(val);
        }else {
            minStack.push(minStack.peek());
        }
    }

    public void pop() {
        if (!stack.isEmpty()){
            stack.pop();
            minStack.pop();
        }
    }

    public int top() {
        if (!stack.isEmpty()){
            return stack.peek();
        }
        return 0;
    }

    public int getMin() {
        return minStack.peek();
    }
}

五、总结

本题使用双栈结构使其检索的时间复杂度达到O(1),并且入栈和出栈的时间复杂度均为O(1)。空间复杂度为O(n)。