注:题目来自于《程序员代码面试指南:IT名企算法与数据结构题目最优解》,该书是左程云老师的著作,值得推荐,这里仅是记录一下该书中题目的解法和个人理解
题目:猫狗队列
宠物、猫、狗的类如下:
public class Pet {
private String type;
public Pet(String type){
this.type = type;
}
public String getPetType(){
return this.type;
}
}
public class Dog extends Pet{
public Dog(String type) {
super("dog");
}
}
public class Cat extends Pet {
public Cat(String type) {
super("cat");
}
}
问题描述:
实现一种猫狗队列的结构,要求如下:
用户可以调用add方法将cat类或dog类的实例放入到队列中;
用户可以调用pollAll方法,将队列中的所有实例按照进队列的先后顺序依次弹出
用户可以调用pollDog方法,将队列中的Dog类的实例按照进队列的先后顺序依次弹出
用户可以调用pollCat方法,将队列中的Cat类的实例按照进队列的先后顺序依次弹出
用户可以调用isEmpty方法,检查队列中是否还有dog或cat的实例
用户可以调用isDogEmpty方法,检查队列中是否还有dog的实例
用户可以调用isCatEmpty方法,检查队列中是否还有cat的实例
思路:
本题考察的是针对特定条件的数据结构设计问题。
改写一个类,记录时间戳
创建两个队列,一个放Dog实例 dogQ,一个放Cat实例catQ
在将实例入队的时候,生成对应的PetEnterQueue类的实例,放入对应的队列中
弹出实例的时候,从对应队列弹出
如果是按实际顺序弹出实例时(pollAll方法),比较对头的时间戳,谁更早就弹出谁
图解:
代码:
包装类:
public 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();
}
}
目标对列:
public class DogCatQueue {
private Queue<PetEnterQueue> dogQ;
private Queue<PetEnterQueue> catQ;
private long count;
public DogCatQueue() {
this.dogQ = new LinkedList<>();
this.catQ = new LinkedList<>();
this.count = 0;
}
public void add(Pet pet) {
if ("dog".equals(pet.getPetType())) {
dogQ.add(new PetEnterQueue(pet, this.count++));
} else if ("cat".equals(pet.getPetType())) {
catQ.add(new PetEnterQueue(pet, this.count++));
} else {
throw new RuntimeException("err,not dog or cat");
}
}
public Queue<Pet> pollAll() {
Queue<Pet> petQ = new LinkedList<>();
while (!dogQ.isEmpty() && !catQ.isEmpty()) {
if (dogQ.peek().getCount() < catQ.peek().getCount()) {
petQ.offer(dogQ.poll().getPet());
} else {
petQ.offer(catQ.poll().getPet());
}
}
while (!dogQ.isEmpty()) {
petQ.offer(dogQ.poll().getPet());
}
while (!catQ.isEmpty()) {
petQ.offer(catQ.poll().getPet());
}
return petQ;
}
public Queue<Dog> pollDog() {
Queue<Dog> printDogQ = new LinkedList<>();
while (!isDogQueueEmpty()) {
printDogQ.offer((Dog) dogQ.poll().getPet());
}
return printDogQ;
}
public Queue<Cat> pollCat() {
Queue<Cat> printCatQ = new LinkedList<>();
while (!isCatQueueEmpty()) {
printCatQ.offer((Cat) catQ.poll().getPet());
}
return printCatQ;
}
public boolean isEmpty() {
return dogQ.isEmpty() && catQ.isEmpty();
}
public boolean isCatQueueEmpty() {
return catQ.isEmpty();
}
public boolean isDogQueueEmpty() {
return dogQ.isEmpty();
}
}
测试类:
public class Test {
public static void main(String[] args) {
DogCatQueue queue = new DogCatQueue();
Dog pet1 = new Dog("dog");
Dog pet2 = new Dog("dog");
Dog pet3 = new Dog("dog");
Cat pet4 = new Cat("cat");
queue.add(pet1);
queue.add(pet2);
queue.add(pet3);
queue.add(pet4);
System.out.println(queue.isEmpty());
queue.pollAll();
System.out.println(queue.isDogQueueEmpty());
System.out.println(queue.isCatQueueEmpty());
queue.add(pet4);
Queue<Dog> dogs = queue.pollDog();
for (Dog dog : dogs) {
System.out.println(dog.getPetType());
}
Queue<Cat> cats = queue.pollCat();
for (Cat cat : cats) {
System.out.println(cat.getPetType());
}
System.out.println(queue.isEmpty());
}
}
测试结果,亲测可用:
false
true
true
cat
true
题目:用一个栈实现另一个栈的排序
问题描述:
一个栈中元素类型为整型,现在想将该栈从顶到底按大到小的顺序排序,只允许申请一个栈,除此之外,可 以申请新的变量,但不能申请额外的数据结构,如何完成排序?
思路:
待排序栈dataStack,辅助栈helpStack
对dataStack进行出栈操作,记作cur,如果cur大于helpStack的栈顶元素,或者helpStack为空,可直接入栈
若cur小于helpstack栈顶元素,则使helpStack栈顶元素出栈,比较新的栈顶元素,知道满足条件,剩下元素 再入栈(递归实现)
图解:
代码:
public class StackOrder {
public static void main(String[] args) {
Stack<Integer> dataStack = new Stack<>();
Stack<Integer> helpStack = new Stack<>();
dataStack.add(3);
dataStack.add(1);
dataStack.add(4);
order(dataStack, helpStack);
for (Integer i : helpStack) {
System.out.println(i);
}
}
private static void order(Stack<Integer> dataStack, Stack<Integer> helpStack) {
if (dataStack == null || dataStack.size() == 0) {
return;
}
while (!dataStack.isEmpty()) {
int cur = dataStack.pop();
helpStackFunction(cur, helpStack);
}
}
private static void helpStackFunction(int cur, Stack<Integer> helpStack) {
if (helpStack.size() == 0 || cur < helpStack.peek()) {
helpStack.push(cur);
return;
}
int i = helpStack.pop();
helpStackFunction(cur, helpStack);
helpStack.push(i);
}
}
测试结果,亲测可用:
4
3
1
注:原著中使用的是循环方法,这里采用的是递归的方法。
关于此书:可以分两次刷,第一次刷1-2星题,第二遍刷3-4星题。循序渐进
关于递归:递归的写法可能不是特别好理解,这里分享一下心得,设计递归时,可以在草纸上画出栈内存的情况,只考虑变量值即可,想象成一个辅助栈,即可降低递归算法的设计难度,屡试不爽。