栈6:最小栈和最大栈3道题
Posted 纵横千里,捭阖四方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈6:最小栈和最大栈3道题相关的知识,希望对你有一定的参考价值。
我们知道栈的特点是每次出栈只能是最后一入栈的那个,但是有些场景需要按照大小的顺序来出栈,这就要栈能够提供每次出栈能够出最大或者最小的那个。这个题目在很多材料里也都会出现,是栈的典型考题之一。我现在找到的有三道:
-
剑指 Offer 30. 包含min函数的栈
-
LeetCode 155 最小栈
-
LeetCode 716 最大栈
我们现在就来看一下怎么做。
1.剑指 Offer 30. 包含min函数的栈
这个题与LeetCode155基本一致, 最小栈题目要求:
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 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.
普通栈的 push() 和 pop() 方法访问top元素的复杂度为 O(1) ;而如果要将 min() 函数复杂度也降为 O(1),一种方式是通过建立辅助栈实现;
-
数据栈 AA :栈 AA 用于存储所有元素,保证入栈 push() 函数、出栈 pop() 函数、获取栈顶 top() 函数的正常逻辑。
-
辅助栈 BB :栈 BB 中存储栈 AA 中所有 非严格降序 的元素,则栈 AA 中的最小元素始终对应栈 BB 的栈顶元素,即 min() 函数只需返回栈 BB 的栈顶元素即可。
因此,只需设法维护好 栈 BB 的元素,使其保持非严格降序,即可实现 min() 函数的 O(1)复杂度。图示:
因为要同时修改两个栈,我们必然要将普通的入栈和出栈方法都作一些改造:
函数设计:
一.push(x) 函数:重点为保持栈 BB 的元素是 非严格降序 的。
-
将 xx 压入栈 AA (即 AA.add(x) );
-
若 ① 栈 BB 为空 或 ② xx 小于等于 栈 BB 的栈顶元素,则将 xx 压入栈 BB (即 B.add(x) )。
二.pop() 函数:重点为保持栈 AA, BB的 元素一致性 。
-
执行栈 AA 出栈(即 AA.pop() ),将出栈元素记为 yy ;
-
若 yy 等于栈 BB 的栈顶元素,则执行栈 BB 出栈(即 BB.pop() )。
三.top() 函数:直接返回栈 AA 的栈顶元素即可,即返回 AA.peek() 。
四.min() 函数:直接返回栈 BB 的栈顶元素即可,即返回 BB.peek() 。
代码如下:
class MinStack {
Stack<Integer> A, B;
public MinStack() {
A = new Stack<>();
B = new Stack<>();
}
public void push(int x) {
A.add(x);
if(B.empty() || B.peek() >= x)
B.add(x);
}
public void pop() {
if(A.pop().equals(B.peek()))
B.pop();
}
public int top() {
return A.peek();
}
public int min() {
return B.peek();
}
}
二.LeetCode716 最大栈
有最小就有最大,这个题目就是前面的最小换成最大。看要求:
设计一个最大栈,支持 push、pop、top、peekMax 和 popMax 操作。
push(x) – 将元素 x 压入栈中。
pop() – 移除栈顶元素并返回这个值。
top() – 返回栈顶元素。
peekMax() – 返回栈中最大元素。
popMax() – 返回栈中最大的元素,并将其删除。如果有多个最大元素,只要删除最靠近栈顶的那个。
这个方法和前面的基本类似,少废话,直接看代码:
class MaxStack {
// 所有值
Stack <Integer> stack = new Stack<Integer>();
// 当前的最大值
Stack <Integer> maxStack = new Stack<Integer>();
public void push(int x) {
// 保证stack和maxStack的元素数量一致, 即便 x == maxStack.peek(), 也会同时push到maxStack和stack
if (maxStack.isEmpty() || x >= maxStack.peek()){
maxStack.push(x);
}
stack.push(x);
}
public int pop() {
if (stack.peek().equals(maxStack.peek())){
maxStack.pop();
}
return stack.pop();
}
public int top() {
return stack.peek();
}
public int peekMax() {
return maxStack.peek();
}
public int popMax() {
Stack <Integer> tempStack = new Stack<Integer>();
int max = maxStack.peek();
while (!stack.peek().equals(maxStack.peek())){
tempStack.push(stack.pop());
}
stack.pop();
maxStack.pop();
while(!tempStack.isEmpty()){
push(tempStack.pop());
}
return max;
}
}
以上是关于栈6:最小栈和最大栈3道题的主要内容,如果未能解决你的问题,请参考以下文章