程序员代码面试指南 —— 栈和队列(二)

注:题目来自于《程序员代码面试指南: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星题。循序渐进
关于递归:递归的写法可能不是特别好理解,这里分享一下心得,设计递归时,可以在草纸上画出栈内存的情况,只考虑变量值即可,想象成一个辅助栈,即可降低递归算法的设计难度,屡试不爽。

猜你喜欢

转载自blog.csdn.net/Kirito19970409/article/details/83750519