注:此博客不再更新,所有最新文章将发表在个人独立博客limengting.site。分享技术,记录生活,欢迎大家关注
1、数组/栈/队列间的转换:
1.1 固定数组实现栈结构:
package sword_to_offer_stack_queue;
public class UseArrayBuildArrayStack {
// 固定数组实现栈
// 准备一个变量index,数组的大小设置为为栈的大小为initSize
// 当要加一个数,index的含义为如果新来一个数,我把新来的数放在index位置
// 当用户让我弹出一个数,我弹出的数是index的下面一个数
// index == size时上一个数下标为size - 1,栈满,如还要压入给用户报错
// index == 0时上一个数下标为-1.栈空,如还要弹出给用户报错
public static class ArrayStack {
private int[] arr;
private int index;
public int size;
public ArrayStack(int initSize) {
if (initSize < 0) {
throw new IllegalArgumentException("The init size is less than 0");
}
this.size = initSize;
arr = new int[initSize];
index = 0;
}
public void push(int num) {
if (index == this.size) {
throw new ArrayIndexOutOfBoundsException("The ArrayStack is full");
}
arr[index++] = num;
}
public int pop() {
if (index == 0) {
throw new ArrayIndexOutOfBoundsException("The ArrayStack is empty");
}
return arr[--index];
}
public int peek() {
if (index == 0) {
throw new ArrayIndexOutOfBoundsException("The ArrayStack is empty");
}
return arr[index - 1];
}
}
public static void main(String[] args) {
ArrayStack arrayStack = new ArrayStack(3);
arrayStack.push(1);
arrayStack.push(3);
arrayStack.push(5);
//arrayStack.push(7);
System.out.println("pop(): " + arrayStack.pop());
System.out.println("pop(): " + arrayStack.pop());
System.out.println("pop(): " + arrayStack.pop());
//System.out.println("pop():" + arrayStack.pop());
}
}
1.2 固定数组实现队列结构:
package sword_to_offer_stack_queue;
public class UseArrayBuildArrayQueue {
// 固定数组实现队列
// 准备一个变量start变量一个end变量,一开始都指向0位置
// 再准备一个size变量约束start和end的行为,size表示队列的大小
// start和end无直接关系(解耦),start或者end都是每次和size比较是否越界
// end代表当要加一个数,我把新来的数放在end位置
// start代表当用户让我取出一个数,我取出的数是start位置的数给用户
// 类似于加数队尾排队打饭,取数队头打完饭走人
// end一旦到底就返回开头,start一直在追end
// nonEmptySize == arr.length 时队列为满,如还要加数给用户报错
// nonEmptySize == 0队列为空,如还要取数给用户报错
public static class ArrayQueue {
private int[] arr;
private int nonEmptySize;
private int start;
private int end;
public ArrayQueue(int initSize) {
if (initSize < 0) {
throw new IllegalArgumentException("The init size is less than 0");
}
arr = new int[initSize];
nonEmptySize = 0;
start = 0;
end = 0;
}
public void add(int num) {
if (nonEmptySize == arr.length) {
throw new ArrayIndexOutOfBoundsException("The ArrayQueue is full");
}
nonEmptySize++;
arr[end] = num;
// end的下一个位置
end = end == arr.length - 1 ? 0 : end + 1;
}
public int poll() {
if (nonEmptySize == 0) {
throw new ArrayIndexOutOfBoundsException("The ArrayQueue is empty");
}
nonEmptySize--;
int tmp = start;
// start的下一个位置
start = start == arr.length - 1 ? 0 : start + 1;
return arr[tmp];
}
public int peek() {
if (nonEmptySize == 0) {
throw new ArrayIndexOutOfBoundsException("The ArrayQueue is empty");
}
return arr[start];
}
}
public static void main(String[] args) {
ArrayQueue arrayQueue = new ArrayQueue(3);
arrayQueue.add(1);
arrayQueue.add(3);
arrayQueue.add(5);
//arrayQueue.add(7);
System.out.println("poll(): " + arrayQueue.poll());
System.out.println("poll(): " + arrayQueue.poll());
System.out.println("poll(): " + arrayQueue.poll());
//System.out.println("poll():" + arrayQueue.poll());
}
}
1.3 仅用栈结构实现队列结构
package sword_to_offer_stack_queue;
import java.util.Stack;
public class UseStackBuildQueue {
// 用栈实现队列结构
// 准备两个栈,一个push栈,一个pop栈
// 加数据入push栈,取数据从pop栈中拿
// 总体思路是进push的数据倒入pop栈中,两次逆序等于顺序
// 倒的两个限制:
// 1) 如果push开始往pop中倒数据,一次要倒完
// 2) pop栈不为空,不允许倒数据
// 只要满足以上两个限制,倒数据的行为可以发生在任何时刻
public static class TwoStackToQueue {
private Stack<Integer> stackPush;
private Stack<Integer> stackPop;
public TwoStackToQueue() {
stackPush = new Stack<>();
stackPop = new Stack<>();
}
private void takeOutData() {
// 2) pop栈不为空,不允许倒数据
if (!stackPop.isEmpty())
return;
// 1) 如果push开始往pop中倒数据,一次要倒完
while (!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
public void add(int num) {
stackPush.push(num);
takeOutData();
}
public int poll() {
if (stackPop.isEmpty() && stackPush.isEmpty()) {
throw new RuntimeException("Queue is empty");
}
takeOutData();
return stackPop.pop();
}
public int peek() {
if (stackPop.isEmpty() && stackPush.isEmpty()) {
throw new RuntimeException("Queue is empty");
}
takeOutData();
return stackPop.peek();
}
}
public static void main(String[] args) {
TwoStackToQueue twoStackToQueue = new TwoStackToQueue();
twoStackToQueue.add(1);
twoStackToQueue.add(3);
twoStackToQueue.add(5);
//twoStackToQueue.add(7);
System.out.println("poll(): " + twoStackToQueue.poll());
System.out.println("poll(): " + twoStackToQueue.poll());
System.out.println("poll(): " + twoStackToQueue.poll());
//System.out.println("poll():" + twoStackToQueue.poll());
}
}
1.4 仅用队列结构实现栈结构
package sword_to_offer_stack_queue;
import java.util.LinkedList;
import java.util.Queue;
public class UseQueueBuildStack {
// 用队列结构实现栈结构
// 准备两个队列,一个data队列,一个help队列
// 压入数入data队列
// 弹出数将data队列中的数除最后一个其他的压入help队列,将最后一个数返回用户,再将data和help引用互换
public static class TwoQueueToStack {
private Queue<Integer> data;
private Queue<Integer> help;
public TwoQueueToStack() {
data = new LinkedList<>();
help = new LinkedList<>();
}
public void push(int num) {
data.add(num);
}
public int pop() {
if (data.isEmpty()) {
throw new RuntimeException("Stack is empty");
}
while (data.size() > 1) {
help.add(data.poll());
}
int res = data.poll();
swap();
return res;
}
public int peek() {
if (data.isEmpty()) {
throw new RuntimeException("Stack is empty");
}
while (data.size() > 1) {
help.add(data.poll());
}
int res = data.poll();
help.add(res);
swap();
return res;
}
private void swap() {
Queue<Integer> tmp = data;
data = help;
help = tmp;
}
}
public static void main(String[] args) {
TwoQueueToStack twoQueueToStack = new TwoQueueToStack();
twoQueueToStack.push(1);
twoQueueToStack.push(3);
twoQueueToStack.push(5);
//twoQueueToStack.push(7);
System.out.println("pop(): " + twoQueueToStack.pop());
System.out.println("pop(): " + twoQueueToStack.pop());
System.out.println("pop(): " + twoQueueToStack.pop());
//System.out.println("pop():" + twoQueueToStack.pop());
}
}
2、添加指定功能修改栈
2.1 实现带getMin()函数的栈
实现一个栈,要求在普通栈的基础上加一个得到所有元素的最小值的函数getMin(),要求时间复杂度O(1)
package sword_to_offer_stack_queue;
import java.util.Stack;
public class GetMinStack {
// 实现一个栈,要求在普通栈的基础上加一个得到所有元素的最小值的函数getMin(),要求时间复杂度O(1)
// 准备两个栈,data栈和min栈
// 数据入data栈的同时,同步将min{min栈栈顶,即将压入data的当前数}压入min栈
// min栈的栈顶就是所有数中的最小元素,data栈和min栈中同步入栈,同步出栈,保持个数一致
public static class minStack1 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public minStack1() {
stackData = new Stack<>();
stackMin = new Stack<>();
}
// 数据入data栈的同时,同步将min{min栈栈顶,即将压入data的当前数}压入min栈
public void push(int num) {
if (stackMin.isEmpty()) {
stackMin.push(num);
} else if (num < stackMin.peek()) {
stackMin.push(num);
} else {
stackMin.push(stackMin.peek());
}
stackData.push(num);
}
// 弹栈你弹我也弹
public int pop() {
if (stackMin.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();
}
}
// 准备两个栈,data栈和min栈
// 当入栈时只有当当前值比min栈栈顶小的时候才将当前值压入min栈
// 当出栈时出栈的值和min栈栈顶比较,若相等则把min栈栈顶移除
// 与minStack1相比节省min相同时的存储空间,每个min只存一份
public static class minStack2 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public minStack2() {
stackData = new Stack<>();
stackMin = new Stack<>();
}
public void push(int num) {
if (stackMin.isEmpty()) {
stackMin.push(num);
} else if (num < stackMin.peek()) {
stackMin.push(num);
}
stackData.push(num);
}
public int pop() {
if (stackData.isEmpty()) {
throw new RuntimeException("Stack is empty");
}
if (stackData.peek() == stackMin.peek()) {
stackMin.pop();
}
return stackData.pop();
}
public int getMin() {
if (stackData.isEmpty()) {
throw new RuntimeException("Stack is empty");
}
return stackMin.peek();
}
}
public static void main(String[] args) {
minStack1 minStack1 = new minStack1();
minStack1.push(3);
System.out.println(minStack1.getMin());
minStack1.push(4);
System.out.println(minStack1.getMin());
minStack1.push(1);
System.out.println(minStack1.getMin());
System.out.println(minStack1.pop());
System.out.println(minStack1.getMin());
System.out.println("=============");
minStack2 minStack2 = new minStack2();
minStack2.push(3);
System.out.println(minStack2.getMin());
minStack2.push(4);
System.out.println(minStack2.getMin());
minStack2.push(1);
System.out.println(minStack2.getMin());
System.out.println(minStack2.pop());
System.out.println(minStack2.getMin());
}
}