【题目1】用数组结构实现大小固定的队列和栈
队列:先进先出
栈:先进后出
【使用固定数组实现栈的功能】
public static class ArrayStack{
private Integer[] arr;
private Integer index;
public ArrayStack(int initSize){
if(initSize < 0){
throw new IllegalArgumentException("The init size is less than 0");
}
arr = new Integer[initSize];
index = 0;
}
public Integer peek(){
if(index == 0){
return null;
}
return arr[index -1];
}
//压栈过程
public push(int obj){
if(index == arr.length){
throw new ArrayIndexOutOfBoundsException("The stack is full");
}
//如果栈没有满,放入新的数字
arr[index++] = obj;
}
//出栈过程
public Integer pop(){
if(index == 0){
throw new ArrayIndexOutOfBoundsException("The stack is empty!");
}
return arr[--index];
}
}
【固定数组实现队列功能】
【思路】定义两个指针,end和start,其中end表示表位位置(进的数应该添加在哪里),start表示表头(出的数从哪里拿)
设置size变量对end和start进行解耦,当size==队列长度的时候不能添加,当size<队列长度的时候可以添加。
public static class ArrayQueue{
//初始化数组,数组大小,开始指针,结束指针
private Integer[] arr;
private Interger size;
private Integer start;
private Integer end;
//初始化该数组队列
public ArrayQueue(int initSize){
if(initSize < 0){
throw new IllegalArgumentException("The init size is less than 0");
}
//对数据进行初始化
arr = new Integer[initSize];
size = 0;
start = 0;
end = 0;
}
//peek返回当前数组队列中的第一个元素是啥
public Interger peek(){
if(size == 0){
return null;
}
return arr[start];
}
//进队操作
public void push(int obj){
//队列满的时候报错
if(size == arr.length){
throw new ArrayIndexOutOfBoundsException("The queue is full");
}
//队列不满则将数字添加到队列中
size++;
arr[end] = obj;
end = nextIndex(arr.length, end);
}
//队列的弹出逻辑
public Integer poll(){
if(size == o){
throw new ArrayIndexOutOfBoundsException("The queue is empty");
}
size--;
int temp = arr[start];
start = nextIndex(arr.length, start);
return temp;
}
}
//nextIndex函数返回index的位置,如果队列满了,则返回开头
public int nextIndex(int size, int index){
return index == size - 1 ? 0 : index + 1;
}
【题目2】实现一个特殊的栈,在实现栈的基本功能的基础上,在实现返回栈中最小元素的操作
【要求】1.pop、push、getMin操作的时间复杂度都是O(1)
2.设计的栈类型可以使用线程的栈
【思路】使用两个栈,另一个栈用来同步存储当前的最小值结构。
public static class MyStack2{
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
//初始化两个栈
public MyStack2(){
this.stackData = new Stack<Integer>();
this.stackMin = new Stack<Integer>();
}
//压栈操作,如果值小于最小栈栈顶直接压入,如果值大于或等于最小栈栈顶则重复压入栈顶值
public void push(int newNum){
if(this.stackMin.isEmpty()){
this.stackMin.push(newNum);
}else if(newNum < this.getmin()){
this.stackMin.push(newNum);
}else{
int newMin = this.stackMin.peek();
this.stackMin.push(newMin);
}
this.stackData.push(newNum);//最后将值压入data栈中
}
public int pop(){
if(this.stackData.isEmpty()){
throw new RuntimeException("Your stack is empty!");
}
this.stackMin.pop();
return stackData.pop();
}
//定义返回最小值栈的栈顶操作
public int getmin(){
if(this.stackMin.isEmpty()){
throw new RuntimeException("Your stack is empty!");
}
return this.stackMin.peek();
}
}
【问题3.1】如何用队列实现栈结构
【思路】使用两个队列循环倒,依次弹出返回每个队列中的最后一个元素,最终得到栈的输出
public static class TwoQueuesStack{
private Queue<Integer> queue;
private Queue<Integer> help;
public TwoQueuesStack(){
queue = new LinkedList<Integer>();
help = new LinkedList<Integer>();
}
public void push(int pushInt){
queue.add(pushInt);
}
//peek功能相当于查看当前栈顶元素
public int peek(){
if(queue.isEmpty()){
throw new RuntimeException("Stack is empty!");
}
while(queue.size() != 1){
help.add(queue.poll());
}
int res = queue.poll();
help.add(res);
swap();
return res;
}
public int pop(){
if(queue.isEmpty()){
throw new RuntimeException("Stack is empty!");
}
//queue中数值>1的时候,依次将queue中的值加入help中去
while(queue.size() > 1){
help.add(queue.poll());
}
//返回queue队列中的剩下最后的一个元素
int res = queue.poll();
//交换引用(queue和help数组进行交换)
swap();
return res;
}
private void swap(){
Queue<Integer> temp = help;
help = queue;
queue = temp;
}
}
【问题3.2】如何用栈结构实现队列结构
【用两个栈实现】将push栈中的元素压入pop栈,即实现与队列相同的先进先出
【注意】(1)pop栈中入股中途还有元素未弹出干净,此时不能往pop栈中压栈(即pop栈未空才能压栈)//
(2)每次从push出栈和压栈进pop一定要倒干净,不能留一些元素
public static class twoStackQueue{
private Stack<Integer> stackPush;
private Stack<Integer> stackPop;
public TwoStacksQueue(){
stackPush = new Stack<Integer>();
stackPop = new Stack<Integer>();
}
public void push(int pushInt){
stackPush.push(pushInt);
dao();
}
public int poll(){
if(stackPop.empty() && stackPush.empty()){
throw new RuntimeException("Queue is empty!");
}
dao();
return stackPop.pop();
}
//当栈之间倒完了才能进行peek操作
public int peek(){
if(stackPop.empty() && stackPush.empty()){
throw new RuntimeException("Queue is empty!")
}
dao();
return stackPop.peek()
}
//将两个栈中的元素进行倒换
public void dao(){
if(stackPop.isEmpty()){ //pop栈必须为空
while(!stackPush.isEmpty()){ //将push栈中元素弹干净
stackPop.push(stackPush.pop());
}
}
}
}