题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
分析
本题的时间复杂度已经确定,那么算法优化就只能从空间复杂度下手,一般来说采用辅助栈保存当前最小值是一个通用解法,这样就需要两个栈。同样我们可以改变栈中保存值,来实现单栈解法。
辅助栈解法
思路很简单,采用一个数据栈保存数据,一个辅助栈保存当前状态下的最小值。
步骤 | 操作 | 数据栈 | 辅助栈 | 最小值 |
---|---|---|---|---|
1 | 压入3 | 3 | 3 | 3 |
2 | 压入4 | 3, 4 | 3, 3 | 3 |
3 | 压入2 | 3, 4, 2 | 3, 3, 2 | 2 |
4 | 压入1 | 3, 4, 2, 1 | 3, 3, 2, 1 | 1 |
5 | 弹出 | 3, 4, 2 | 3, 3, 2 | 2 |
6 | 弹出 | 3, 4 | 3, 3 | 3 |
7 | 压入0 | 3, 4, 0 | 3, 3, 0 | 0 |
最小值为辅助栈的栈顶
以下为具体解答:
private Stack<Integer> dataStack = new Stack<>();
private Stack<Integer> minStack = new Stack<>();
public void push(int node) {
dataStack.push(node);
if (minStack.isEmpty() || node < minStack.peek()) {
minStack.push(node);
} else {
minStack.push(minStack.peek());
}
}
public void pop() {
dataStack.pop();
minStack.pop();
}
public int top() {
return dataStack.peek();
}
public int min() {
return minStack.peek();
}
单栈解法
此时数据栈中保存的肯定不是实际的数据,我们引入一个类变量 min 用于保存当前时刻的最小值,数据栈中保存的是相对于 min 的变化值。
举例说明
当min 为 2 时。
- 压入 3,数据栈压入3 - 2 = 1;
- 压入 1,数据栈压入1 - 2 = -1,同时min更新为 1。
- 弹出时,检查数据栈的栈顶元素,若大于 0,说明上次压入没有更新 min 的值,直接弹出栈顶;若小于 0 ,则需要更新 min 为 newMin = oldMin - 栈顶元素。
注意该方法数据栈压入的是long数据类型。这是由于变化值若为Integer.MAX_VALUE - Integer.MIN_VALUE 的话就超出Integer的范围了。
以下为具体解答:
private Stack<Long> stack = new Stack<>();;
private long min;
public void push(int node) {
if (stack.empty()) {
stack.push((long)0);
min = node;
} else {
stack.push((long)node-min);
if (node < min) {
min = node;
}
}
}
public void pop() {
if (!stack.empty()) {
if (stack.peek() < 0) {
min = min - stack.peek();
}
stack.pop();
}
}
public int top() {
if (stack.empty()) {
throw new RuntimeException("empty stack");
} else {
if (stack.peek() > 0) {
return (int)(min + stack.peek());
} else {
return (int)min;
}
}
}
public int min() {
if (stack.empty()) {
throw new RuntimeException("empty stack");
} else {
return (int)min;
}
}