第二次碰到这道题了,又学了两种解题方法,记录一下。
题目介绍
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
解法一:使用辅助栈
这个也是最简单的,题目没有空间限制,考虑使用两个栈,主栈正常记录元素进出,辅助栈记录每个元素对应最小值的进出,辅助栈的栈顶保持为主栈所有元素的最小值。
当元素入栈时,比较该元素和辅助栈的栈顶,如果该元素更小,那么将其推入主栈的同时也将其推入辅助栈。
当元素出栈时,如果主栈栈顶元素值和辅助栈的栈顶元素值相等。那么将该元素从两个栈里同时弹出,否则正常弹出主栈栈顶元素。
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
| class MinStack { Deque<Integer> stack1; Deque<Integer> stack2; public MinStack() { stack1 = new ArrayDeque<>(); stack2 = new ArrayDeque<>(); } public void push(int val) { stack1.push(val); if (stack2.isEmpty() || val <= stack2.peek()) { stack2.push(val); } } public void pop() { int num = stack1.pop(); if (num == stack2.peek()) stack2.pop(); } public int top() { return stack1.peek(); } public int getMin() { return stack2.peek(); } }
|
解法二:使用自定义链表
评论区有评论说面试官要求使用栈以外的数据结构来设计,所以找到这种方法。
每个节点存储三个值:该节点的值,整个链表的最小值,指向下一个节点的指针。我设计的是头插法,head 指向表头,也可以看作栈顶。
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 Node { int val; int minVal; Node next; public Node(int val, int minVal) { this.val = val; this.minVal = minVal; } public Node(int val, int minVal, Node next) { this.val = val; this.minVal = minVal; this.next = next; } } class MinStack {
Node head; public MinStack() { } public void push(int val) { if (head == null) { head = new Node(val, val); } else { head = new Node(val, Math.min(val, head.minVal), head); } } public void pop() { head = head.next; } public int top() { return head.val; } public int getMin() { return head.minVal; } }
|
解法三:使用O(1)的辅助空间
如果只是存储节点值使用 int 即可,而中间要计算差值,考虑到溢出的可能性,所以使用 long 类型来存储。注意 long 和 int 之间的转换。
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 { Deque<Long> stack = new ArrayDeque<>(); long min; public MinStack() {
}
public void push(int val) { if (stack.isEmpty()) { stack.push(0L); min = val; } else { long diff = val - min; stack.push(diff); if (diff < 0) min = val; } }
public void pop() { Long pop = stack.pop(); if (pop < 0) min -= pop; }
public int top() { Long peek = stack.peek(); if (peek < 0) return (int)min; return (int)min + peek.intValue(); }
public int getMin() { return (int)min; } }
|