1.设计一个有getMin功能的栈
1.解题思路
方案一:
push:将每次插入的新值和stackMin的栈顶元素比较,如果新值较小就插入到stackMin,否则什么也不干
pop:stackData出栈的元素如果是栈中最小元素,则stackMin对应的元素也要出栈
方案二:
push:将方案二“什么也不干”这件事改为重复插入stackMin栈顶元素
pop:因为push操作重复的插入,则pop时不需要比较stackData出栈元素是否是stackMin栈顶元素,两个栈 同步出栈即可。
2.遇到的问题
- 方案一为什么能保证stackMin栈顶元素是此时stackData所有元素的最小值
- 因为压栈的时候stackMin总是与插入的值比较,保持栈顶是最小值
- 方案二为什么要同步压入
- 因为可以同步出栈
3.代码
代码:
//方案一
public class MyStack1{
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public MyStack1(){
this.stackData = new Stack<>();
this.stackMin = new Stack<>();
}
public void push(int newNum){
if (stackMin.isEmpty()) {
stackMin.push(newNum);
}
else{
if (newNum <= getMin()) {
stackMin.push(newNum);
}
}
stackData.push(newNum);
}
public int pop(){
if (stackData.isEmpty()) {
throw new RuntimeException("Stack is Empty");
}
int value = stackData.pop();
if (value == getMin()) {
stackMin.pop();
}
return value;
}
public int getMin(){
if (stackMin.isEmpty()) {
throw new RuntimeException("Stack is Empty");
}
return stackMin.peek();
}
}
//方案二
public class MyStack2{
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public MyStack2(){
this.stackData = new Stack<>();
this.stackMin = new Stack<>();
}
public void push(int newNum){
if (stackMin.isEmpty()) {
stackMin.push(newNum);
}
else{
if (newNum < getMin()) {
stackMin.push(newNum);
}
else{
//重复压入最小值
stackMin.push(getMin());
}
}
stackData.push(newNum);
}
public int pop(){
if (stackData.isEmpty()) {
throw new RuntimeException("Stack is Empty");
}
stackMin.pop();
return stackData.pop();
}
public int getMin(){
if (stackMin.isEmpty()) {
throw new RuntimeException("Stack is Empty");
}
return stackMin.peek();
}
}
4.收获
一个栈不能解决的问题,那就用两个栈
2.由两个栈组成的队列
编写一个类,用两个栈实现队列,支持队列的基本操作(add、poll、peek)
1.解题思路
先将数压入stackPush栈,再将stackPush栈中的数出栈到stackPop
期间需满足:
- 如果stackPop栈不为空,stackPush不能出栈到stackPop
- 如果stackPop能出栈,则要一次性出完
2.遇到的问题
3.代码
代码
public class TwoStacksQueue{
public Stack<Integer> stackPush;
public Stack<Integer> stackPop;
public TwoStacksQueue(){
stackPush = new Stack<Integer>();
stackPop = new Stack<Integer>();
}
public void add(int pushInt){
stackPush.push(pushInt);
}
public int poll(){
if (!stackPop.isEmpty()) {
return stackPop.pop();
}
else{
if (stackPush.isEmpty()) {
throw new RuntimeException("Queue is empty!!");
}
else{
while (!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}
}
public int peek(){
if (!stackPop.isEmpty()) {
return stackPop.peek();
}
else{
if (stackPush.isEmpty()) {
throw new RuntimeException("Queue is empty!!");
}
else{
while (!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.peek();
}
}
}
4.收获
抓住了栈和队列的特点
栈:先进后出
队列:先进先出
3.如何仅用递归函数和栈操作逆序一个栈
1.解题思路
getLastAndRemove递归方法流程:
reverse递归方法流程: