[LeetCode] 155. Min Stack

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:
-231 <= val <= 231 - 1
Methods pop, top and getMin operations will always be called on non-empty stacks.
At most 3 * 104 calls will be made to push, pop, top, and getMin.

最小栈。

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

实现 MinStack 类:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这个题我给出两种解法,一种用了两个 stack,一种只需要用一个 stack。两种做法的复杂度都是
时间O(1)
空间O(n)

思路一 - 两个stack

两个 stack。创建两个 stack,一个叫 stack,另一个叫做 minstack。

  • push() - 每当需要 push 的时候,每个元素都会被正常 push 到 stack,同时需要看一下当前元素与全局最小元素 min 的关系,以决定是否需要把这个元素 push 到 minStack。minStack 只 push 当前遍历到的最小值。

  • pop() - stack 会正常 pop 出当前元素;因为 minStack 的顶端存的永远是当前的最小值,所以当 stack 弹出一个元素 X 的时候,需要去 minStack 的栈顶看一下 X 是不是最小值,也就是看一下 minStack 的栈顶是不是也是 X,如是,也需要从 minStack 弹出,这样 minStack 顶端保留的永远是最小值。

  • top() - 同 peek(),只是看一下 stack 顶端的元素

  • getMin() - 去 peek minStack 顶端的元素,因为 minStack 的顶端永远是当前遍历到的最小值

代码

Java实现

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
class MinStack {
private Stack<Integer> stack;
private Stack<Integer> minStack;
/** initialize your data structure here. */
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}

public void push(int x) {
stack.push(x);
if (!minStack.isEmpty()) {
int min = minStack.peek();
if (x <= min) {
minStack.push(x);
}
} else {
minStack.push(x);
}
}

public void pop() {
int x = stack.pop();
if (x == minStack.peek()) {
minStack.pop();
}
}

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

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

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

JavaScript实现

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
51
52
53
54
55
56
57
/**
* initialize your data structure here.
*/
var MinStack = function () {
this.stack = [];
this.minStack = [];
};

/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function (x) {
this.stack.push(x);
if (this.minStack.length) {
let top = this.minStack[this.minStack.length - 1];
if (x <= top) {
this.minStack.push(x);
}
} else {
this.minStack.push(x);
}
};

/**
* @return {void}
*/
MinStack.prototype.pop = function () {
let pop = this.stack.pop();
let top = this.minStack[this.minStack.length - 1];
if (pop === top) {
this.minStack.pop();
}
};

/**
* @return {number}
*/
MinStack.prototype.top = function () {
return this.stack[this.stack.length - 1];
};

/**
* @return {number}
*/
MinStack.prototype.getMin = function () {
return this.minStack[this.minStack.length - 1];
};

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

思路二 - 一个stack

一个 stack,同时创建一个变量记录最小值 min。我参考了这个帖子的解法二。

  • push() - push 的时候看一下当前元素是否比 min 小,若是则把上一个min再次放进stack,同时更新当前最小值 min。

  • pop() - 如果弹出值 == 当前最小值,那么再弹一次的值为上一个最小值也即出栈后更新的最小值

  • top() - 同 peek,只是看一下 stack 顶端的元素

  • getMin() - 输出 min 即可

代码

Java实现

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
class MinStack {
Stack<Integer> stack;
int min;

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

public void push(int val) {
if (val <= min) {
stack.push(min);
min = val;
}
stack.push(val);
}

public void pop() {
if (stack.pop() == min) {
min = stack.pop();
}
}

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

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();
*/

JavaScript实现

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
51
52
53
54
55
/**
* initialize your data structure here.
*/
var MinStack = function () {
this.stack = [];
this.min = Number.MAX_SAFE_INTEGER;
};

/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function (x) {
// 当前值比min值更小
if (this.min >= x) {
// 将上一个min最小值保存入栈
this.stack.push(this.min);
// 更新当前最小值
this.min = x;
}
this.stack.push(x)
};

/**
* @return {void}
*/
MinStack.prototype.pop = function () {
// 如果弹出值 == 当前最小值,那么再弹一次的值为上一个最小值也即出栈后更新的最小值
if (this.stack.pop() == this.min) {
this.min = this.stack.pop();
}
};

/**
* @return {number}
*/
MinStack.prototype.top = function () {
return this.stack[this.stack.length - 1];
};

/**
* @return {number}
*/
MinStack.prototype.getMin = function () {
return this.min;
};

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

相关题目

1
2
155. Min Stack
716. Max Stack

[LeetCode] 155. Min Stack
https://shurui91.github.io/posts/4038167410.html
Author
Aaron Liu
Posted on
February 18, 2020
Licensed under