文章目录
- 总述
- 一、以O(1)的时间复杂度获取栈中最小元素
- 方法一
- 1、思路
- 2、代码
- 方法二
- 1、思路
- 2、代码
- 二、用两个栈构建出一个队列
- 1、思路
- 2、代码
- 3、测试
- 三、用两个队列构建出一个栈
- 1、思路
- 2、代码
- 3、测试
总述
有些面试官喜欢让你用栈实现BFS、用队列实现DFS,其实就是间接让你用栈实现队列、用队列实现栈;千万不要死脑筋想着就用一个栈实现队列、用一个队列实现栈;往往都是需要用两个栈实现一个队列,用两个队列实现一个栈。
一、以O(1)的时间复杂度获取栈中最小元素
实现一个栈,在基本功能的基础上,实现返回栈中最小元素的功能;要求以O(1)的时间复杂度获取到栈中的最小元素。
方法一
1、思路
第一种push的方式,当要push的数字 不大于 最小栈中的栈顶数字时,才将数字放入到最小栈;
第一种pop的方式,当要pop的数字 等于 最小栈中的栈顶数字时,才将数字pop出最小栈;
2、代码
public class Main {
private Stack<Integer> dataStack;
private Stack<Integer> minStack;
public Main() {
dataStack = new Stack<>();
minStack = new Stack<>();
}
public void push(Integer num) {
// 要push的数字 不大于 最小栈中的栈顶数字,则将数字放入到最小栈
if (minStack.isEmpty() || num <= getMin()) {
minStack.push(num);
}
dataStack.push(num);
}
public Integer pop() {
if (dataStack.isEmpty()) {
throw new RuntimeException("Stack is empty!");
}
Integer value = dataStack.pop();
if (value == getMin()) {
minStack.pop();
}
return value;
}
public Integer getMin() {
return minStack.peek();
}
}
方法二
1、思路
第二种push的方式,每次push时将 要push的数字 和 最小栈中的栈顶数字 中的最小值 push到最小栈。
第二种pop的方式,每次pop时,最小栈也同步pop。
2、代码
public class Main {
private Stack<Integer> dataStack;
private Stack<Integer> minStack;
public Main() {
dataStack = new Stack<>();
minStack = new Stack<>();
}
public void push(Integer num) {
// 要push的数字 不大于 最小栈中的栈顶数字,则将数字放入到最小栈
if (minStack.isEmpty() || num < getMin()) {
minStack.push(num);
} else {
int currMin = minStack.peek();
minStack.push(currMin);
}
dataStack.push(num);
}
public Integer pop() {
if (dataStack.isEmpty()) {
throw new RuntimeException("Stack is empty!");
}
minStack.pop();
return dataStack.pop();
}
public Integer getMin() {
return minStack.peek();
}
}
二、用两个栈构建出一个队列
使用栈设计一个队列结构
1、思路
栈:FILO,队列:FIFO
一个栈用于push,一个栈用于pop栈;提供一个函数pushToPop()当pushStack 不为空,popStack为空时,将push栈的数据全部反转放到pop栈;每次push、pop、peek是都调用函数pushToPop()。
2、代码
public class Main {
private Stack<Integer> pushStack;
private Stack<Integer> popStack;
public Main() {
pushStack = new Stack<>();
popStack = new Stack<>();
}
public void enqueue(int val) {
pushStack.push(val);
pushToPop();
}
public int dequeue() {
if (popStack.empty() && pushStack.empty()) {
throw new RuntimeException("queue is empty!");
}
pushToPop();
return popStack.pop();
}
public int peek() {
if (popStack.empty() && pushStack.empty()) {
throw new RuntimeException("queue is empty!");
}
pushToPop();
return popStack.peek();
}
public void pushToPop() {
// 如果popStack不为空时,直接将pushStack中的数据放到popStack中,会导致数据错乱
if (popStack.isEmpty()) {
while (!pushStack.empty()) {
popStack.push(pushStack.pop());
}
}
}
}
3、测试
public static void main(String[] args) {
Main test = new Main();
test.enqueue(1);
test.enqueue(2);
test.enqueue(3);
System.out.println(test.peek());
System.out.println(test.dequeue());
System.out.println(test.peek());
System.out.println(test.dequeue());
System.out.println(test.peek());
System.out.println(test.dequeue());
}
三、用两个队列构建出一个栈
使用队列设计一个栈结构;
1、思路
一个队列用于存放数据,一个队列作为辅助队列;
当要从队列中取一个数据时,将数据队列中的数据只留一个,其余全部移动到辅助队列,数据队列中保留的一个数据作为结果返回;最后再将辅助队列 和 数据队列 交换,供下一次存数据、 取数据使用。
2、代码
public class Main {
private Queue<Integer> queue;
private Queue<Integer> help;
public Main() {
this.queue = new LinkedList<>();
this.help = new LinkedList<>();
}
public void push(int val) {
queue.offer(val);
}
public int pop() {
while (queue.size() > 1) {
help.offer(queue.poll());
}
Integer res = queue.poll();
Queue<Integer> temp = queue;
queue = help;
help = temp;
return res;
}
public int peek() {
while (queue.size() > 1) {
help.offer(queue.poll());
}
Integer res = queue.poll();
help.offer(res);
Queue<Integer> temp = queue;
queue = help;
help = temp;
return res;
}
public boolean isEmpty() {
return queue.isEmpty();
}
}
3、测试
public static void main(String[] args) {
Main myStack = new Main();
Stack<Integer> stack = new Stack<>();
myStack.push(1);
myStack.push(2);
myStack.push(3);
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(myStack.peek());
System.out.println(stack.peek());
System.out.println("------------");
System.out.println(myStack.pop());
System.out.println(stack.pop());
System.out.println("------------");
System.out.println(myStack.pop());
System.out.println(stack.pop());
System.out.println("------------");
System.out.println(myStack.peek());
System.out.println(stack.peek());
}