最小栈
实现一个栈,该栈带有出栈,入栈,取最小值 3 个方法。保证这三个方法的时间复杂度都是。
- 设原有的栈叫作栈 A,此时创建一个额外的“备胎”栈 B,用于辅助栈 A。
- 当第 1 个元素进入栈 A 时,让新元素也进入栈 B。这个唯一的元素是栈 A 的当前最小值。
- 之后,每当新元素进入栈 A 时,比较新元素和栈 A 当前最小值的大小,如果小于栈 A 当前最小值,则让新元素进入栈 B,此时栈 B 的栈顶元素就是栈 A 当前最小值。
- 每当栈A有元素出栈时,如果出栈元素是栈 A 当前最小值,则让栈 B 的栈顶元素也出栈。此时栈 B 余下的栈顶元素所指向的,是栈 A 当中原本第 2 小的元素,代替刚才的出栈元素成为栈 A 的当前最小值。(备胎转正。)
当调用 getMin 方法时,返回栈 B 的栈顶所存储的值,这也是栈 A 的最小值。
public class MinStack {
private Stack<Integer> mainStack = new Stack<>();
private Stack<Integer> minStack = new Stack<>();
// 入栈
public void push(int element) {
mainStack.push(element);
// 如果辅助栈为空,或者新元素小于或等于辅助栈栈顶元素,则将新元素入栈
if (minStack.empty() || element <= minStack.peek()) {
minStack.push(element);
}
}
// 出栈
public Integer pop() {
// 如果出栈元素和辅助栈栈顶元素值相等,辅助栈出栈
if (mainStack.peek().equals(minStack.peek())) {
minStack.pop();
}
return mainStack.pop();
}
// 获取栈的最小元素
public int getMin() throws Exception {
if (mainStack.empty()) {
throw new Exception("stack is empty");
}
return minStack.peek();
}
public static void main(String[] args) throws Exception {
MinStack stack = new MinStack();
stack.push(4);
stack.push(9);
stack.push(7);
stack.push(3);
stack.push(8);
stack.push(5);
System.out.println(stack.getMin());
stack.pop();
stack.pop();
stack.pop();
System.out.println(stack.getMin());
}
}
如何用栈实现队列
用栈来模拟一个队列,要求实现队列的两个基本操作:入队、出队。
这里可以使用两个栈来模拟队列操作,假设有栈A,栈B两个栈,我们可以用栈A 模拟入队操作,用栈B模拟出队操作,具体操作流程如下:
- 让元素依次插入栈A;
- 假设现在需要出栈,将栈A中的元素依次出栈,并按照出栈顺序依次压入栈B;
- 出栈时依次从栈B弹出元素;
- 有新的元素入栈时,让其继续压入栈A;
- 出栈时若栈B不为空,则继续从栈B中弹出元素,若栈B为空,则重复第2步;
……
public class StackImplQueue {
private Stack<Integer> stackA = new Stack<>();
private Stack<Integer> stackB = new Stack<>();
// 入队
public void enqueue(int element) {
stackA.push(element);
}
// 出队
public Integer deQueue() {
if (stackB.isEmpty()) {
if (stackA.isEmpty()) {
return null;
}
transfer();
}
return stackB.pop();
}
// 栈 A 元素移到栈 B
private void transfer() {
while (!stackA.isEmpty()) {
stackB.push(stackA.pop());
}
}
public static void main(String[] args) {
StackImplQueue stackImplQueue = new StackImplQueue();
stackImplQueue.enqueue(1);
stackImplQueue.enqueue(2);
stackImplQueue.enqueue(3);
System.out.println(stackImplQueue.deQueue());
System.out.println(stackImplQueue.deQueue());
stackImplQueue.enqueue(4);
System.out.println(stackImplQueue.deQueue());
System.out.println(stackImplQueue.deQueue());
}
}