题目
算法思路
要使
m
i
n
(
)
min()
min() 方法时间复杂度只有
O
(
1
)
O(1)
O(1),不难想到 “以空间换时间”,使用辅助栈存储最小值。
注意这里的辅助栈和数据栈可以是同步的,也可以是不同步的。前者代码简单,但存储了很多“不必要”的元素,后者节约了空间,但增加了代码的复杂程度。
方法一
使用一个辅助栈,与数据栈同步插入与删除,用于存储与每个元素对应的最小值。
- 当一个元素要入栈时,取当前辅助栈的栈顶,与当前元素比较得出最小值,将其压入辅助栈;
- 当一个元素要出栈时,将辅助栈的栈顶元素一并弹出;
- 在任意时刻,数据栈内元素的最小值就存储在辅助栈的栈顶。
具体代码
class MinStack {
Stack<Integer> A;//数据栈
Stack<Integer> B;//辅助栈
/** initialize your data structure here. */
public MinStack() {
A = new Stack<>();
B = new Stack<>();
B.push(Integer.MAX_VALUE);//整型上限压入辅助栈
}
/* 将元素x压栈 */
public void push(int x) {
A.push(x);
B.push(Math.min(x, B.peek()));
}
/* 删除栈顶元素 */
public void pop() {
A.pop();
B.pop();
}
/* 获取栈顶元素 */
public int top() {
return A.peek();
}
/* 获取栈中最小元素 */
public int min() {
return B.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.min();
*/
复杂度分析
- 时间复杂度: O ( 1 ) O(1) O(1),四个函数的时间复杂度均为常数级别
- 空间复杂度: O ( n ) O(n) O(n),最坏情况下数据栈中的元素非严格递减,则辅助栈的额外空间开销就会达到 O ( n ) O(n) O(n)
方法二
在方法一的基础上改进辅助栈的构造,在一般情况下可以减小辅助栈的空间开销,即 “不与数据栈同步”。对于 p u s h ( ) push() push() 函数,只有当前进栈元素小于原有的最小元素时才会将其压入辅助栈;对于 p o p ( ) pop() pop() 函数,当数据栈中出栈的元素等于辅助栈栈顶元素时,才会执行辅助栈的出栈操作。
具体代码
class MinStack {
Stack<Integer> A;//数据栈
Stack<Integer> B;//辅助栈
/** initialize your data structure here. */
public MinStack() {
A = new Stack<>();
B = new Stack<>();
}
/* 将元素x压栈 */
public void push(int x) {
A.push(x);
if(B.empty() || B.peek() >= x)B.push(x);
}
/* 删除栈顶元素 */
public void pop() {
if(A.peek().equals(B.peek())){
B.pop();
}
A.pop();
}
/* 获取栈顶元素 */
public int top() {
return A.peek();
}
/* 获取栈中最小元素 */
public int min() {
return B.peek();
}
}
复杂度分析
- 时间复杂度: O ( 1 ) O(1) O(1),四个函数的时间复杂度均为常数级别
- 空间复杂度: O ( n ) O(n) O(n),虽然一般情况下此改进可以减少辅助栈中的元素,但最坏情况下,也就是数据栈中的元素非严格递减时,辅助栈的额外空间开销仍会达到 O ( n ) O(n) O(n)