015 最小栈-力扣155

实现常数时间获取最小值的栈(MinStack)。主流方法是维护一个辅助栈记录每个位置的最小值,保证getMin()的O(1)复杂度。文章展示了基于Java内置栈、数组以及单链表三种实现方式,链表解法每个节点额外存储当前最小值。

Posted by Hilda on March 25, 2025

概览:

155. 最小栈

力扣155. 最小栈

155. 最小栈

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

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

示例 1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
输入:
["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.

提示:

  • -231 <= val <= 231 - 1
  • poptopgetMin 操作总是在 非空栈 上调用
  • push, pop, top, and getMin最多被调用 3 * 104

解法:自己尝试写的

image-20250325205506594

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class MinStack {


    int min;
    int[] stack;
    int size;

    public MinStack() {
        stack = new int[30000];
        size = 0;
    }

    public void push(int val) {
        if (size == 0) {
            min = val;
        } else {
            min = min < val ? min : val;
        }
        stack[size++] = val;
    }

    public void pop() {
        if (size == 1) {
            size--;
            return;
        }
        min = stack[size - 2];
        size--;
        for (int i = size - 1; i >= 0; i--) {
            min = min < stack[i] ? min : stack[i];
        }
    }

    public int top() {
        return stack[size - 1];
    }

    public int getMin() {
        return min;
    }
}

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

解法2:最小栈

除了数据栈,单独另外准备一个栈,记录这个位置下栈的最小值。

例如:

数据栈:3,7,2,5,7(如果一直不pop的话)

最小栈:3,3,2,2,2

如果pop那么最小栈也要相应pop

代码1:Java内部Stack

image-20250325210607437

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class MinStack {

    Stack<Integer> data;
    Stack<Integer> min;

    public MinStack() {
        data = new Stack<>();
        min = new Stack<>();
    }

    public void push(int x) {
        data.push(x);
        if (min.isEmpty() || min.peek() > x) {
            min.push(x);
        } else {
            min.push(min.peek());
        }
    }

    public void pop() {
        data.pop();
        min.pop();
    }

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

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

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

实现2:数组实现栈

image-20250325211325686

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class MinStack {

    int MAXN = 7500;//不断提交得到的

    int[] data;
    int[] min;
    int size;

    public MinStack() {
        data = new int[MAXN];
        min = new int[MAXN];
    }

    public void push(int x) {
        data[size] = x;
        if (size == 0 || min[size - 1] > x) {
            min[size] = x;
        } else {
            min[size] = min[size - 1];
        }
        size++;
    }

    public void pop() {
        size--;
    }

    public int top() {
        return data[size - 1];
    }

    public int getMin() {
        return min[size - 1];
    }
}

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

所以,我打算看看那top3%到底是什么解法。

解法3:单链表实现栈

image-20250325212856952

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class MinStack {
    class Node{
        int val;
        int minVal;
        Node next;
        public Node(int val, int minVal){
            this.val = val;
            this.minVal = minVal;
        }
    }
    public Node preHead = new Node(-1, -1);

    public MinStack() {
        
    }
    
    public void push(int val) {
        Node node = new Node(val, val);
        if (preHead.next != null && preHead.next.minVal < val){
            node.minVal = preHead.next.minVal;
        }
        node.next = preHead.next;
        preHead.next = node;
    }
    
    public void pop() {
        preHead.next = preHead.next.next;
    }
    
    public int top() {
        return preHead.next.val;
    }
    
    public int getMin() {
        return preHead.next.minVal;
    }
}

数据结构:使用单链表,每个节点 (Node) 包含:

  • val:当前元素值
  • minVal:截至该节点时的最小值
  • next:指向下一个节点的指针

哨兵节点:preHead 作为头节点的前置节点,便于操作。