题目一:用数组结构实现队列和栈
难度相当于一面第一道题的难度
队列结构:先入先出FIFO
栈结构:先入后出
实现栈:设置一个指针index,起始位置指向0的位置,读取一个数据则将数据放到数组【0】的位置,然后index++,之后新进来一个数则index++,取出数则index–。同时注意index的取值范围为0–size-1.
用数组实现栈
public static class ArrayStack{
private Integer[] arr;
private Integer size;
public ArrayStack(int initSize){
if(initSize<0){
throw new IllegalArgumentException("The init size is less than 0");
}
arr = new Integer[initSize];
size = 0;
}
//如果数组现在长度为0,那么返回空,如果不为0,现在数组中有值,则将最后一个数据取出。
public Integer peek(){
if(size ==0){
return null
}
return arr[size-1];
}
//将数据存入栈中,如果存入数据的数目超过了栈(数组)本身的长度,则会弹出异常
//没有超过时则将新读取的数据存放到数组之中,同时将size加一
public void push(int obj){
if(size == arr.length){
throw new ArrayIndexOutOfBoundsException("the queue is full");
}
arr[size++] = obj;
}
//将数据弹出栈,只要长度不为0,那么就弹出最后一个数据,同时将size的长度减一
public void pop(){
if(size == 0){
throw new ArrayIndexOutOfBoundException("the queue is empty");
}
return arr[--size];
}
}
数组表示队列
public static class ArrayQueue{
private Integer[] arr;
private Integer size;
private Integer first;
private Integer last;
public ArrayQueue(int initSize){
if(initSize<0){
throw new IllegalArgumentException("the init size is less than 0");
}
arr = new Integer[initsize];
size = 0;
first = 0;
last = 0;
}
public Integer peek(){
if(size == 0){
return null
}
return arr[first];
}
//数据读取到数组中跟数据读出是相同的操作,这里的精髓在于将last和first指针重新归零,这样数组长度不变,形成一个圆的循环,使得数据可以不断的存储和取出,形成一个队列。
public void push(int obj){
if(size == arr.length){
throw new ArrayIndexOutOfBoundsException("the queue is full");
}
size++;
arr[last] = obj;
last = last == arr.length-1 ? 0 : last+1;
}
//将数据读取出,读取的过程是将first指针进行向后移动,同时进行first是否到了最底端,如果到了则归零,不到则继续向后读取数据
public Integer poll(){
if(size == 0){
throw new ArrayIndexOutOfBoundsException("the queue is empty");
}
size--;
int tmp = first;
first = first == arr.length-1 ? 0 : first+1;
return arr[tmp];
}
}
数组实现栈结构和队列结构,需要自己可以顺利编写出来,需要多加练习。
题目二:实现一个特殊的栈,实现栈的基础功能的同时,再返回栈中最小元素的操作
【要求】:pop,push,getmin操作时间复杂度都为O(1),设计的栈类型可以采用现成的栈结构。
个人理解:如果题目要求时间复杂度较小,而自己可以想到一种时间复杂度较大的方法,则可以尝试将空间复杂度增大而减少时间复杂度
本题一眼看过去觉得可以采用遍历的方法,可以寻找到栈中最小的元素,但是遍历的过程时间复杂度较高,复杂度为O(N),不符合要求,所以可以想办法提高空间复杂度,可以多创立一个数组或栈,第一个栈中可以用于存放基本的栈的功能,第二个栈中可以进行最大最小值的比较。
public static class MyStack1{
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public Mystack1(){
this.stackData = new Stack<Integer>();
this.stackMin = new Stack<Integer>();
}
//放入最小值堆栈中时,此处仅放置比当前最小值小的数值,另一种思路是如果当前数值大于目前最小值,则将最小值再次放入到数组之中,做到跟正常栈中数据数目相同,同时push和pop
public void push(int newNum){
if(this.stackMin.isEmpty()){
this.stackMin.push(newNum);
}else if(newNum<=this.getmin()){
this.stackMin.push(newNum);
}
this.stackData.push(newNum);
}
//放入数据方式不同,因此最小值栈弹出数据方式也不同,先比较data栈中弹出数值和当前最小值是否相等, 不相等则不弹出,相等才弹出
public int pop(){
if(this.stackData.isEmpty()){
throw new RuntimeException("your stack is empty");
}
int value = this.stackData.pop();
if(value == this.getmin()){
this.stackMin.pop();
}
return value;
}
public int getMin(){
if(this.stackMin.isEmpty()){
throw new RuntimeException("your stack is empty");
}
return this.stackMin.peek();
}
}
题目三:队列结构实现栈结构/栈结构实现队列结构
队列结构实现栈结构:用两个队列,将先入的数据存储到另外一个队列之中,只剩下最后一个数据用于弹出。之后还要求弹出还是一样的将其他数据全部存储到另一个队列之中,只剩最后一个数据用于弹出。数据存储则按照队列的形式存储。
两个队列实现栈
public static class TwoQueuesStack{
private Queue<Integer> queue;
private Queue<Integer> help;
private TwoQueuesStack(){
queue = new LinkedList<Integer>();
help = new LinkedList<Integer>();
}
public void push(int pushInt){
queue.add(pushInt);
}
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");
}
while(queue.size()>1){
help.add(queue.poll());
}
int res = queue.poll();
swap();
return res;
}
//将两个队列进行名称互换,实现转换
private void swap(){
queue<Integer> tmp = help;
help = queue;
queue = tmp;
}
}
题目四:猫狗队列
//定义一个父类,存在两个子类,猫和狗
public static class Pet{
private String type;
public Pet(String type){
this.type = type;
}
public String getPetType(){
return this.type;
}
}
//子类继承父类
public static class Dog extends Pet{
public Dog(){
super("dog");
}
}
public static class Cat extends Pet{
public Cat(){
super("cat");
}
}
//将宠物读取到队列之中,同时宠物有独立的计数系统
public static class PetEnterQueue{
private Pet pet;
private Long count;
public PetEnterQueue(Pet pet,long count){
this.pet = pet;
this.count = count;
}
public Pet getPet(){
return this.pet;
}
public long getCount(){
return this.count;
}
public String getEnterPetType(){
return this.pet.getPetType();
}
}
//设置猫和狗的队列,在add的时候需要判断宠物类型,再放入对应的两个队列中。
public static class dogCatQueue{
private Queue<PetEnterQueue> dogQ;
private Queue<PetEnterQueue> catQ;
private long count;
public DogCatQueue(){
this.dogQ = new linkedList<PetEnterQueue>();
this.catQ = new linkedList<petEnterQueue>();
this.count = 0;
}
public void add(Pet pet){
if(pet.getPetType().equals("dog")){
this.dogQ.add(new PetEnterQueue(pet,this.count++));
}else if(pet.getPetType().equals("cat")){
this.catQ.add(new PetEnterQueue(pet,this.count++));
}else{
throw new RuntimeException("err,not dog or cat");
}
}
//由于队列的特性是先入先出,因此在这里判断队列中count值的大小,因为两个队列公用一个count,因此可以知道存入的顺序,再按照顺序依次读出就可以
public Pet pollAll(){
if(!this.dogQ.isEmpty()&&!this.catQ.isEmpty()){
if(this.dogQ.peek().getCount()<this.catQ.peek().getCount()){
return this.dogQ.poll().getPet();
}else{
return this.catQ.poll().getPet();
}
//只有当两个队列其中一个为空的时候才可能退出,跳转到下面
}else if (!this.dogQ.isEmpty()){
return this,dogQ.poll().getPet();
}else if(!this.catQ.isEmpty()){
return this.catQ.poll().getPet();
}else{
throw new RuntimeException("err");
}
}
public Dog pollDog(){
if(!this.isDogQueueEmpty()){
return (Dog) this.dogQ.poll().getPet();
}else{
throw new RuntimeException("Dog queue empty");
}
}
public Cat pollCat(){
if(!this.isCatQueueEmpty(){
return (Cat) this.catQ.poll().getPet();
}else{
throw new RuntimeException("cat queue is Empty"):
}
}
public boolean isEmpty(){
return this.dogQ.isEmpty() &&this.catQ.isEmpty();
}
public boolean isDogQueueEmpty(){
return this.dogQ.isEmpty();
}
public boolean isCatQueueEmpty(){
return this.catQ.isEmpty();
}
}
猫狗问题中,可以采用三个队列,分别存储猫队列,狗队列和全部的宠物队列,上述做法只采用了两个队列,将两个队列同时计数,具有唯一性,因此省掉第三个总队列,将空间复杂度降低,时间复杂度相同。