LeetCode_151_最小栈

482 阅读2分钟

题目

155. 最小栈

难度 简单

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

  • 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.

提示:

  • poptopgetMin 操作总是在 非空栈 上调用。

辅助栈

我们要维持正常栈的特性,比如说pop() top() push(x)。所以我们需要一个正常的栈来存储数据。同时我们需要一个方法来获取剩余元素中的最小值,这个也可以使用栈来实现。这个用来辅助记录的栈,我们称为 辅助栈

image-20210106111713751

如上图,我们在每存储一个元素时,判断是否比当前栈顶元素大,如果大则再次存入之前的栈顶元素。这样生成的右边栈,就是与左边栈一一对应,当前栈的最小值。需要注意左边pop时右边也要pop,保持一直,这样右边栈顶元素一直是左边栈剩余元素的最小值。如下图:

image-20210106112144831

代码实现

import java.util.Stack;

//leetcode submit region begin(Prohibit modification and deletion)
class MinStack {
    Stack<Integer> normalStack;
    Stack<Integer> minStack;

    /**
     * initialize your data structure here.
     */
    public MinStack() {
        normalStack = new Stack<>();
        minStack = new Stack<>();
    }

    public void push(int x) {
        normalStack.push(x);
        if (minStack.isEmpty()) {
            minStack.push(x);
        } else {
            if (x <= minStack.peek()) {
                minStack.push(x);
            } else {
              //如果存入的值比当前栈顶大,那么再存入一个当前栈顶的元素
                minStack.push(minStack.peek());
            }
        }
    }

    public void pop() {
        normalStack.pop();
        minStack.pop();
    }

    public int top() {
        return normalStack.peek();
    }

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

解法优化

上面说道的使用 辅助栈的解法,比较好理解,个人推荐。不过提交后,发现其实还有其他更优的解法。

image-20210106115813287

如上图,自定义一个Node,里面除了存储Next,Value还记录当前的最小值。而且构建链表的时候注意是 反向链表。这样最后一个元素就存在head的位置。

我们top()getMin()都是取head就行。

push(x)的时候存储value外,需要比较下x与之前head的min的哪个小的,存储小的。

class MinStack {
	//自定义一个Node,里面除了存储Next,Value还记录当前的最小值
   class Node {
        private int min;
        private int val;
        private Node next;

        private Node(int val, int min) {
            this(val, min, null);
        }

        private Node(int val, int min, Node next) {
            this.val = val;
            this.min = min;
            this.next = next;
        }
    }
  
 Node head;

    public MinStack() {

    }

    public void push(int x) {
        if (head == null) {
            head = new Node(x, x);
        } else {
          // push(x)的时候存储value外,需要比较下x与之前head的min的哪个小的,存储小的。
          // 反向链表
            head = new Node(x, Math.min(x, head.min), head);
        }

    }

    public void pop() {
        head = head.next;

    }

    public int top() {
        return head.val;
    }

    public int getMin() {
        return head.min;
    }

}

运行结果:

image-20210106120433275

相似题型:面试题 03.02. 栈的最小值