题目 #
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
Implement the MinStack class:
- MinStack() initializes the stack object.
- void push(int val) pushes the element val onto the stack.
- void pop() removes the element on the top of the stack.
- int top() gets the top element of the stack.
- int getMin() retrieves the minimum element in the stack.
You must implement a solution with O(1) time complexity for each function.
Example 1:
Input
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
Output
[null,null,null,null,-3,null,0,-2]
Explanation
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); // return -3
minStack.pop();
minStack.top(); // return 0
minStack.getMin(); // return -2
Constraints:
- $-2^{31} <= val <= 2^{31} - 1$
- Methods pop, top and getMin operations will always be called on non-empty stacks.
- At most $3 \times 10^4$ calls will be made to push, pop, top, and getMin.
思路1 两个栈 #
分析 #
- 用一个栈存最小值,一个栈存值
- 节省空间就当值小于等于最小值才入最小值栈,同理只要出栈等于最小值,就出最小值栈
代码 #
1type MinStack3 struct {
2 stack []int
3 minStack []int
4}
5
6func Constructor3() MinStack {
7 return &MinStack3{
8 stack: make([]int, 0),
9 minStack: make([]int, 0),
10 }
11}
12
13func (this *MinStack3) Push(val int) {
14 this.stack = append(this.stack, val)
15 if len(this.minStack) == 0 || val <= this.minStack[len(this.minStack)-1] {
16 this.minStack = append(this.minStack, val)
17 }
18}
19
20func (this *MinStack3) Pop() {
21 if len(this.stack) == 0 {
22 return
23 }
24 v := this.stack[len(this.stack)-1]
25 this.stack = this.stack[:len(this.stack)-1]
26 if this.minStack[len(this.minStack)-1] == v {
27 this.minStack = this.minStack[:len(this.minStack)-1]
28 }
29}
30
31func (this *MinStack3) Top() int {
32 return this.stack[len(this.stack)-1]
33}
34
35func (this *MinStack3) GetMin() int {
36 return this.minStack[len(this.minStack)-1]
37}
思路2 一个栈,存放值和最小值 #
分析 #
- 如何使用一个栈,考虑将最小值也放到这个栈里面,那么就是当值小于等于最小值时,先push前一次最小值,再push值
- 出栈时,如果值和当前最小值一样,下一个就是前一次最小值
代码 #
1type MinStack2 struct {
2 stack []int
3 min int
4}
5
6func Constructor2() MinStack {
7 return &MinStack2{
8 stack: make([]int, 0),
9 min: math.MaxInt,
10 }
11}
12
13func (this *MinStack2) Push(val int) {
14 if val <= this.min {
15 this.stack = append(this.stack, this.min)
16 this.min = val
17 }
18 this.stack = append(this.stack, val)
19}
20
21func (this *MinStack2) Pop() {
22 if len(this.stack) == 0 {
23 return
24 }
25 v := this.stack[len(this.stack)-1]
26 this.stack = this.stack[:len(this.stack)-1]
27 if v == this.min {
28 this.min = this.stack[len(this.stack)-1]
29 this.stack = this.stack[:len(this.stack)-1]
30 }
31}
32
33func (this *MinStack2) Top() int {
34 return this.stack[len(this.stack)-1]
35}
36
37func (this *MinStack2) GetMin() int {
38 return this.min
39}
思路3 一个栈,存放值和最小值的差值 #
分析 #
- 一个栈加当前的int可以存放两个信息,如果栈里面存放的是值和当前最小值的差值就可以办到
- 入栈没什么说的,先入差值再判断是不是要更新最小值,因为先更新最小值会把前一次最小值的信息丢失掉
- 出栈就比较精髓了,当出栈的值小于0,说明入栈时值小于最小值,那么最小值就是当前值,而前一次最小值可以用当前值减去差值算出来
代码 #
1type MinStack1 struct {
2 stack []int
3 min int
4}
5
6func Constructor() MinStack {
7 return &MinStack1{
8 stack: make([]int, 0),
9 min: math.MaxInt,
10 }
11}
12
13func (this *MinStack1) Push(val int) {
14 if len(this.stack) == 0 {
15 this.min = val
16 this.stack = append(this.stack, val-this.min)
17 } else {
18 this.stack = append(this.stack, val-this.min)
19 if val < this.min {
20 this.min = val
21 }
22 }
23}
24
25func (this *MinStack1) Pop() {
26 if len(this.stack) == 0 {
27 return
28 }
29 v := this.stack[len(this.stack)-1]
30 this.stack = this.stack[:len(this.stack)-1]
31 if v < 0 {
32 this.min -= v
33 }
34}
35
36func (this *MinStack1) Top() int {
37 v := this.stack[len(this.stack)-1]
38 if v < 0 {
39 return this.min
40 }
41 return this.min + v
42}
43
44func (this *MinStack1) GetMin() int {
45 return this.min
46}