04_猫狗队列

简介: 04_猫狗队列

猫狗队列

【题目】

宠物、狗和猫的类如下:

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() {
        super("dog");
    }
}
public class Cat extends Pet {
    public Cat() {
        super("cat");
    }
}

实现一种狗猫队列的结构,要求如下:

  • 用户可以调用add方法将cat类或dog类的实例放入队列中;
  • 用户可以调用pollAll方法,将队列中所有的实例按照进队列的先后顺序依次弹出;
  • 用户可以调用pollDog方法,将队列中dog类的实例按照进队列的先后顺序依次弹出;
  • 用户可以调用isEmpty方法,检查队列中是否还有dog或cat的实例;
  • 用户可以调用isDogEmpty方法,检查队列中是否有dog类的实例;
  • 用户可以调用isCatEmpty方法,检查队列中是否有Cat类的实例。

注意:

  1. cat队列只放cat实例,dog队列只放dog实例,再用一个总队列放所有的实例。
    错误原因:cat、dog以及总队列的更新问题
  2. 用哈希表,key表示一个cat实例或dog实例,value表示这个实例进队列的次序。
    错误原因:不能支持一个实例多次进队列的功能需求,因为哈希表的key只能对应一个value值。
  3. 将用户原有的cat或dog类改写,加一个计数项来表示某一个实例进队列的时间。
    错误原因:不能擅自改变用户的类结构。

参考代码如下:

import java.util.Queue;
import java.util.LinkedList;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
// 如何解决不能修改封装的类
/**
 * 1. 在实际情况下,对于封装好的类往往不能修改其中的代码,如何对其增加属性呢?即对其进行再封装
 * 2. 在本题中,有两个类,它们有沟通的父类,为了对两个类一起封装,采用了封装其共同父类的方法。
 */
class Pet {
    private String type;
    private int id;
    public Pet(String type, int id) {
        this.type = type;
        this.id = id;
    }
    public String getPetType() {
        return this.type;
    }
    public int getId() {
        return this.id;
    }
}
class Cat extends Pet {
    public Cat(int id) {
        super("cat", id);
    }
}
class Dog extends Pet {
    public Dog(int id) {
        super("dog", id);
    }
}
// 创建一个类, 用于收容上述两个类
class PetEnter {
    // 增加一个变量,记录数量,作为时间戳
    private Pet pet;
    private long count;
    public PetEnter(Pet pet, long count) {
        this.pet = pet;
        this.count = count;
    }
    public Pet getPet() {
        return this.pet;
    }
    public long getCount() {
        return this.count;
    }
    public String getPetEnterType() {
        return this.pet.getPetType();
    }
}
// 使用两个队列存放不同的类
/**
 * 1.为了存放不同的两个类,一种办法是放到一个队列中,操作的时候,每一次都要出队,包括弹出队列,判断队列中的每一个类是否为空,时间复杂度较高
 * 2.使用"空间换时间"的思想,将两个类的对立队列封装好,使用时间戳的方式记录其进入队列的顺序,这样既可以操作总的序列,也可以单独操作不同的类
 */
class DogCatQueue {
    private Queue<PetEnter> catQueue;
    private Queue<PetEnter> dogQueue;
    private long count;  // 时间戳
    public DogCatQueue() {
        this.catQueue = new LinkedList<>();
        this.dogQueue = new LinkedList<>();
        this.count = 0;
    }
    // 用户调用add方法可以将cat或者dog放入队列中
    public void add(Pet pet) {
        //按照类型放入动物队列中
        if (pet.getPetType().equals("dog")) {
            this.dogQueue.add(new PetEnter(pet, this.count++));
        } else if (pet.getPetType().equals("cat")) {
            this.catQueue.add(new PetEnter(pet, this.count++));
        } else {
            throw new RuntimeException("error no thus class");
        }
    }
    public Pet pollAll() {
        if (!this.catQueue.isEmpty() && !this.dogQueue.isEmpty()) {
            if (this.catQueue.peek().getCount() < this.dogQueue.peek().getCount()) {
                return this.catQueue.poll().getPet();
            } else {
                return this.dogQueue.poll().getPet();
            }
            //否则就是其中一个为空
        } else if (!this.catQueue.isEmpty()) {  //狗空了,猫没有空
            return this.catQueue.poll().getPet();
        } else if (!this.dogQueue.isEmpty()) { //猫空了, 狗没有空
            return this.dogQueue.poll().getPet();
        } else {
            return null;
        }
    }
    public Pet pollDog() {
        if (!this.dogQueue.isEmpty()) {
            return this.dogQueue.poll().getPet();
        }
        return null;
    }
    public Pet pollCat() {
        if (!this.catQueue.isEmpty()) {
            return this.catQueue.poll().getPet();
        }
        return null;
    }
    // 判断队列是否为空
    public boolean isEmpty() {
        if (this.dogQueue.isEmpty() && this.catQueue.isEmpty()) {
            return true;
        }
        return false;
    }
    // 判断狗队列是否为空
    public boolean isDogEmpty() {
        if (this.dogQueue.isEmpty()) {
            return true;
        }
        return false;
    }
    // 判断猫队列是否为空
    public boolean isCatEmpty() {
        if (this.catQueue.isEmpty()) {
            return true;
        }
        return false;
    }
    public static void main(String[] args) throws IOException {
        DogCatQueue dogCatQueue = new DogCatQueue();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(reader.readLine());
        // 保存结果的数组
        for (int i = 0; i < N; ++i) {
            StringBuilder result = new StringBuilder();
            String[] strArr = reader.readLine().split(" ");
            String option = strArr[0];
            switch (option) {
                case "add":
                    String type = strArr[1];
                    if (type.equals("dog")) {
                        int id = Integer.parseInt(strArr[2]);
                        dogCatQueue.add(new Pet("dog", id));
                    } else if (type.equals("cat")) {
                        int id = Integer.parseInt(strArr[2]);
                        dogCatQueue.add(new Pet("cat", id));
                    }
                    break;
                case "pollAll":
                    while (!dogCatQueue.isEmpty()) {
                        Pet pet = dogCatQueue.pollAll();
                        result.append(pet.getPetType()).append(" ").append(pet.getId()).append("\n");
                    }
                    System.out.print(result);
                    break;
                case "pollDog":
                    while (!dogCatQueue.isDogEmpty()) {
                        Pet pet = dogCatQueue.pollDog();
                        result.append(pet.getPetType()).append(" ").append(pet.getId()).append("\n");
                    }
                    System.out.print(result);
                    break;
                case "pollCat":
                    while (!dogCatQueue.isCatEmpty()) {
                        Pet pet = dogCatQueue.pollCat();
                        result.append(pet.getPetType()).append(" ").append(pet.getId()).append("\n");
                    }
                    System.out.print(result);
                    break;
                case "isDogEmpty":
                    System.out.println(dogCatQueue.isDogEmpty() ? "yes" : "no");
                    break;
                case "isCatEmpty":
                    System.out.println(dogCatQueue.isCatEmpty() ? "yes" : "no");
                    break;
                case "isEmpty":
                    System.out.println(dogCatQueue.isEmpty() ? "yes" : "no");
                    break;
            }
        }
    }
}

本题在牛客网上也有对应的原题,可找到!!!!

相关文章
|
6月前
|
Java 网络安全 Apache
SshClient应用指南:使用org.apache.sshd库在服务器中执行命令。
总结起来,Apache SSHD库是一个强大的工具,甚至可以用于创建你自己的SSH Server。当你需要在服务器中执行命令时,这无疑是非常有用的。希望这个指南能对你有所帮助,并祝你在使用Apache SSHD库中有一个愉快的旅程!
357 29
|
8月前
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
264 16
|
9月前
|
存储 前端开发 Java
【SpringMVC】——Cookie和Session机制
获取URL中参数@PathVarible,上传文件@RequestPart,HttpServerlet(getCookies()方法,getAttribute方法,setAttribute方法,)HttpSession(getAttribute方法),@SessionAttribute
212 11
|
10月前
|
存储 缓存 监控
Java中的线程池深度解析####
本文深入探讨了Java并发编程中的核心组件——线程池,从其基本概念、工作原理、核心参数解析到应用场景与最佳实践,全方位剖析了线程池在提升应用性能、资源管理和任务调度方面的重要作用。通过实例演示和性能对比,揭示合理配置线程池对于构建高效Java应用的关键意义。 ####
|
12月前
|
缓存 NoSQL 应用服务中间件
Redis实战篇
Redis实战篇
|
12月前
|
存储 索引 Python
python中的数据容器
python中的数据容器
|
机器学习/深度学习 人工智能 数据可视化
探索Open Interpreter(开放代码解释器)
探索Open Interpreter(开放代码解释器)
302 1
|
SQL 关系型数据库 MySQL
(十七)SQL优化篇:如何成为一位写优质SQL语句的绝顶高手!
(Structured Query Language)标准结构化查询语言简称SQL,编写SQL语句是每位后端开发日常职责中,接触最多的一项工作,SQL是关系型数据库诞生的产物,无论是什么数据库,MySQL、Oracle、SQL Server、DB2、PgSQL....,只要还处于关系型数据库这个范畴,都会遵循统一的SQL标准,这句话简单来说也就是:无论什么关系型数据库,本质上SQL的语法都是相同的,因为它们都实现了相同的SQL标准,不同数据库之间仅支持的特性不同而已。
528 8
|
前端开发 网络协议
Netty实战巅峰:从零构建高性能IM即时通讯系统,解锁并发通信新境界
【8月更文挑战第3天】Netty是一款高性能、异步事件驱动的网络框架,适用于开发高并发网络应用,如即时通讯(IM)系统。本文将指导你利用Netty从零构建高性能IM程序,介绍Netty基础及服务器/客户端设计。服务器端使用`ServerBootstrap`启动,客户端通过`Bootstrap`连接服务器。示例展示了简单的服务器启动过程。通过深入学习,可进一步实现用户认证等功能,打造出更完善的IM系统。
397 1
|
缓存 Java API
Java API设计实战指南:打造稳健、用户友好的API
本文将深入探讨在Java中设计有效API的原则,并着重介绍RESTful设计原则、版本控制策略以及文档实践。
700 38