剑指 Offer 30(栈堆队列2).包含min函数的栈
问题描述:
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.min(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.min(); --> 返回 -2.
解题思路:思路链接
本题难点: 将 min() 函数复杂度降为 O(1) ,可通过建立辅助栈实现;
- 数据栈 stackA : 栈 A 用于存储所有元素,保证入栈 push() 函数、出栈 pop() 函数、获取栈顶 top() 函数的正常逻辑。
- 辅助栈 stackB : 栈 B 中存储栈 stackA 中所有 非严格降序 的元素,则栈stackA 中的最小元素始终对应栈 BB 的栈顶元素,即 min() 函数只需返回栈 stackB 的栈顶元素即可。
因此,只需设法维护好 栈 stackB 的元素,使其保持非严格降序,即可实现 min() 函数的O(1) 复杂度。
算法过程:
1.push(x) 方法: 重点为保持栈stackB 的元素是 非严格降序 的。
- 将 x 压入栈 stackA (即 stackA.add(x) );
- 若 ① 栈 stackB 为空 或 ② x 小于等于 栈 stackB 的栈顶元素,则将 x 压入栈 stackB (即 stackB.add(x) )。
2.pop() 方法: 重点为保持栈stackA,stackB 的 元素一致性 。
- 执行栈 stackA 出栈(即 stackA.pop() ),将出栈元素记为 y ;
- 若 y 等于栈 stackB 的栈顶元素,则执行栈 stackB 出栈(即 stackB.pop() )。
3.top() 方法: 直接返回栈 stackA 的栈顶元素即可,即返回 stackA.peek() 。
4.min() 方法: 直接返回栈 stackB 的栈顶元素即可,即返回 stackB.peek() 。
补充说明:
- stack.peek() 返回栈顶元素,但不在堆栈中删除它。
- stack.pop() 返回栈顶元素,并在进程中删除它。
使用递归代码实现:
class MinStack {
public Stack<Integer> stackA;
public Stack<Integer> stackB;
/** initialize your data structure here. */
public MinStack() {
//建立两个栈,一个用于存储所有元素,一个作为辅助栈输出最小值
stackA = new Stack<>();
stackB = new Stack<>();
}
public void push(int x) {
stackA.add(x);
if(stackB.isEmpty() || stackB.peek() >= x){
stackB.add(x);
}
}
public void pop() {
//当A栈中弹出的元素与和B栈的栈顶元素相同时,弹出B栈中的栈顶元素
if(stackA.pop().equals(stackB.peek())){
stackB.pop();
}
}
public int top() {
//获取A栈的栈顶元素
return stackA.peek();
}
public int min() {
//获取B栈栈顶元素,此时B的栈顶元素为A栈中的最小值
return stackB.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();
*/