LeetCode:855. 考场就座(TreeSet Java)

news2024/12/24 15:38:29

目录

855. 考场就座

题目描述:

实现代码与解析:

TreeSet

原理思路:


855. 考场就座

题目描述:

        在考场里,有 n 个座位排成一行,编号为 0 到 n - 1

当学生进入考场后,他必须坐在离最近的人最远的座位上。如果有多个这样的座位,他会坐在编号最小的座位上。(另外,如果考场里没有人,那么学生就坐在 0 号座位上。)

设计一个模拟所述考场的类。

实现 ExamRoom 类:

  • ExamRoom(int n) 用座位的数量 n 初始化考场对象。
  • int seat() 返回下一个学生将会入座的座位编号。
  • void leave(int p) 指定坐在座位 p 的学生将离开教室。保证座位 p 上会有一位学生。

示例 1:

输入:
["ExamRoom", "seat", "seat", "seat", "seat", "leave", "seat"]
[[10], [], [], [], [], [4], []]
输出:
[null, 0, 9, 4, 2, null, 5]
解释:
ExamRoom examRoom = new ExamRoom(10);
examRoom.seat(); // 返回 0,房间里没有人,学生坐在 0 号座位。
examRoom.seat(); // 返回 9,学生最后坐在 9 号座位。
examRoom.seat(); // 返回 4,学生最后坐在 4 号座位。
examRoom.seat(); // 返回 2,学生最后坐在 2 号座位。
examRoom.leave(4);
examRoom.seat(); // 返回 5,学生最后坐在 5 号座位。

提示:

  1. 1 <= n <= 109
  2. 保证有学生正坐在座位 p 上。
  3. seat 和 leave 最多被调用 104 次。

实现代码与解析:

TreeSet

import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.TreeSet;

class ExamRoom {

    int n;
    private PriorityQueue<int[]> ts = new PriorityQueue<>((a, b) -> {
        int d1 = dist(a), d2 = dist(b);
        return d1 == d2 ? a[0] - b[0] : d2 - d1;
    });


    private Map<Integer, Integer> left = new HashMap<>();
    private Map<Integer, Integer> right = new HashMap<>();

    public ExamRoom(int n) {
        this.n = n;
        add(-1, n);
    }

    public int seat() {
        int[] peek = ts.peek();
        int p = (peek[0] + peek[1]) >> 1;
        if (peek[0] == -1) p = 0;
        else if (peek[1] == n) p = n - 1;
        del(peek);
        add(peek[0], p);
        add(p, peek[1]);
        return p;
    }

    public void leave(int p) {
        int l = left.get(p);
        int r = right.get(p);
        del(new int[]{l, p});
        del(new int[]{p, r});
        add(l, r);
    }

    public void add(int l, int r) {
        ts.add(new int[]{l, r});
        left.put(r, l);
        right.put(l, r);
    }

    public void del(int[] q) {
        ts.remove(q);
        left.remove(q[1]);
        right.remove(q[0]);
    }

    private int dist(int[] q) {
        int l = q[0], r = q[1];
        return l == -1 || r == n ? r - l - 1 : (r - l) >> 1;
    }

}

/**
 * Your ExamRoom object will be instantiated and called as such:
 * ExamRoom obj = new ExamRoom(n);
 * int param_1 = obj.seat();
 * obj.leave(p);
 */

原理思路:

1. 重要的成员变量

        int n:表示考场中座位的总数,限定了座位范围的边界值。

        TreeSet<int[]> ts:这是一个自定义比较器的TreeSet,用来存储表示座位区间的数组。比较器的逻辑是先比较区间的 “距离”(通过dist方法计算,距离的定义与区间两端的情况有关),如果距离相等则按照区间左端点的大小来排序。其目的是方便快速找到最合适的空闲座位区间来分配座位。

        Map<Integer, Integer> leftMap<Integer, Integer> right:这两个HashMap分别用于记录每个座位区间的左端点对应的右端点,以及右端点对应的左端点,方便在座位分配和释放操作时快速查找和更新区间的关联关系。

2. 构造函数

        public ExamRoom(int n):构造函数接收表示座位总数的参数n,初始化this.n为传入的n值,并且调用add(-1, n)方法,将初始的整个考场座位区间(从虚拟的-1到实际的n,代表初始全部空闲的状态)添加到数据结构中进行管理。

3. seat方法(座位分配方法)

        首先获取ts中第一个(按照自定义比较器排序最合适的)座位区间数组peek

然后计算要分配的座位位置p,计算规则是取区间的中间位置(通过(peek[0] + peek[1]) >> 1,也就是取平均值向下取整),同时针对区间左端点是-1(代表最左边开始的区间)或者右端点是n(代表最右边的区间)的特殊情况,进行边界处理,分别将座位分配到最左边(p = 0)或者最右边(p = n - 1)。

        接着通过del方法移除当前选中的座位区间,再调用两次add方法,将因为分配座位而产生的两个新的区间添加到数据结构中,最后返回分配的座位位置p

4. leave方法(座位释放方法)

        接收要释放的座位位置参数p,通过leftright这两个Map获取该座位所在区间的左端点l和右端点r

        调用del方法移除包含该座位的两个区间(分别是[l, p][p, r]),然后调用add方法将合并后的区间[l, r]重新添加到数据结构中,表示座位释放后区间状态的更新。

5. add方法(添加区间方法)

        接收区间的左端点l和右端点r作为参数,将代表区间的数组{l, r}添加到ts中,同时在leftright这两个Map中分别添加对应端点的关联关系,方便后续查找和更新操作。

6. del方法(移除区间方法)

        接收表示区间的数组q作为参数,从ts中移除该区间,同时在leftright这两个Map中移除对应端点的关联记录,实现区间从数据结构中的彻底删除。

7. dist方法(计算区间距离方法)

        接收表示区间的数组q,获取其左端点l和右端点r,根据区间两端是否是边界情况(l == -1或者r == n)来计算区间的 “距离”,如果是边界情况距离计算为r - l - 1,否则为(r - l) >> 1(即区间长度的一半),这个距离值用于在TreeSet的比较器中判断区间的优先级,从而确定分配座位时优先选择的区间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2264795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2四、 scoped样式冲突,data是一个函数,组件通信-父传子-子传父-非父子

组件通信 1. 父组件通过 props 将数据传递给子组件 2. 子组件利用 $emit 通知父组件修改更新 父--->子 子--->父

第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ

Q1、统计符合条件长度为3的子数组数目 1、题目描述 给你一个整数数组 nums &#xff0c;请你返回长度为 3 的子数组&#xff0c;满足第一个数和第三个数的和恰好为第二个数的一半。 子数组 指的是一个数组中连续 非空 的元素序列。 2、解题思路 我们需要在给定的数组 nums…

PSDK的编译与ROS包封装

本文档讲述在NIVIDIA开发板上使用大疆提供的Payload SDK获取无人机实时GPS信息的方法&#xff0c;以及基于Payload SDK发布ROS GPS话题信息的方法。 文章目录 0 实现目标1 Payload SDK1.1 PSDK 源码的编译1.2 PSDK 的使用 2 遥测数据的读取2.1 示例代码结构2.2 读取机载GPS信息…

铝电解电容使用寿命

铝电解电容寿命问题 铝电解电容为什么会失效&#xff1f;铝电解电容失效与那些因素有关&#xff1f;电解电容寿命如何计算&#xff1f; 1铝电解电容为什么会失效&#xff1f; 电容都是由两个导电板并排放到一起就构成了。正极是铝&#xff08;阳极箔&#xff09;&#xff0c;…

用Python PySide6 复刻了两软件UI 做下练习

图样 1 代码 1&#xff1a; # -*- coding: utf-8 -*-import sys from PySide6.QtCore import (QCoreApplication, QMetaObject, QRect, QDate) from PySide6.QtGui import QIcon, QPixmap, QColor from PySide6.QtWidgets import (QApplication, QDialog, QLineEdit, QPushBut…

安装MongoDB,环境配置

官网下载地址&#xff1a;MongoDB Shell Download | MongoDB 选择版本 安装 下载完成双击打开 点击mongodb-windows-x86_64-8.0.0-signed 选择安装地址 检查安装地址 安装成功 二.配置MongoDB数据库环境 1.找到安装好MongoDB的bin路径 复制bin路径 打开此电脑 -> 打开高级…

Spring学习(一)——Sping-XML

一、Spring的概述 (一)什么是Spring? Spring是针对bean对象的生命周期进行管理的轻量级容器。提供了功能强大IOC、AOP及Web MVC等功能。Spring框架主要由七部分组成&#xff1a;分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 S…

重温设计模式--职责链模式

文章目录 职责链模式的详细介绍C 代码示例C示例代码2 职责链模式的详细介绍 定义与概念 职责链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它旨在将请求的发送者和多个接收者解耦&#xff0c;让多个对象都有机会处理请求&a…

easegen将教材批量生成可控ppt课件方案设计

之前客户提出过一个需求&#xff0c;就是希望可以将一本教材&#xff0c;快速的转换为教学ppt&#xff0c;虽然通过人工程序脚本的方式&#xff0c;已经实现了该功能&#xff0c;但是因为没有做到通用&#xff0c;每次都需要修改脚本&#xff0c;无法让客户自行完成所有流程&am…

高考志愿填报:如何制定合理的志愿梯度?

高考志愿填报中常见的避雷行为&#xff0c;深入分析了专业选择、招生政策了解、学校选择、备选方案准备以及防诈骗等方面的关键问题&#xff0c;并提出了针对性的建议与策略。旨在为考生和家长提供实用的指导&#xff0c;助力考生科学合理地填报高考志愿&#xff0c;避免陷入各…

如何查看vivado项目所使用的版本

在我们提供的各类教程中vivado使用的版本都不同&#xff0c;而使用不同版本的vivado打开项目时可能会产生一些其它错误&#xff0c;所有最好使用对应的vivado版本打开&#xff0c;本例主要演示如何查看项目所示使用的vivado版本。 如下图所示&#xff0c;为vivado2023.1版本创建…

ue5 pcg(程序内容生成)真的简单方便,就5个节点

总结&#xff1a; 前情提示 鼠标单击右键平移节点 1.编辑-》插件-》procedural->勾选两个插件 2.右键-》pcg图表-》拖拽进入场景 3.先看点point 右键-》调试(快捷键d)->右侧设置粒子数 3.1调整粒子数 可以在右侧输入框&#xff0c;使用加减乘除 4.1 表面采样器 …

光谱相机在农业的应用

一、作物生长监测1、营养状况评估 原理&#xff1a;不同的营养元素在植物体内的含量变化会导致植物叶片或其他组织的光谱反射率特性发生改变。例如&#xff0c;氮元素是植物叶绿素的重要组成部分&#xff0c;植物缺氮时&#xff0c;叶绿素含量下降&#xff0c;其在可见光波段&a…

基于Springboot的数字科技风险报告管理系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有实…

14,攻防世界Web_php_unserialize

进入场景 看见代码&#xff0c;解析一下 这段PHP代码定义了一个名为Demo的类&#xff0c;并演示了如何通过URL参数进行反序列化和文件高亮显示的功能&#xff0c;同时也包含了一些安全措施以防止对象注入攻击。下面是对这段代码的逐行解释&#xff1a; 1.<php 开始PHP代码…

基于NodeMCU的物联网窗帘控制系统设计

最终效果 基于NodeMCU的物联网窗帘控制系统设计 项目介绍 该项目是“物联网实验室监测控制系统设计&#xff08;仿智能家居&#xff09;”项目中的“家电控制设计”中的“窗帘控制”子项目&#xff0c;最前者还包括“物联网设计”、“环境监测设计”、“门禁系统设计计”和“小…

【Linux开发工具】自动化构建-make/Makefile

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;【Linux开发工具】gcc和g &#x1f516;流水不争&#xff0c;争的是滔滔不 一、make和Makefile简介1.1 什么是…

Elasticsearch安装和数据迁移

Elasticsearch安装和数据迁移 Elasticsearch安装 下载并解压Elasticsearch 首先下载Elasticsearch的tar.gz文件&#xff0c;并将其解压&#xff1a; wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.8.2-linux-x86_64.tar.gz tar -xzf elastics…

dockerfile文档编写(1):基础命令

目录 Modelscope-agentARGFROMWORKDIRCOPYRUNENVCMD run_loopy Modelscope-agent ARG BASE_IMAGEregistry.cn-beijing.aliyuncs.com/modelscope-repo/modelscope:ubuntu22.04-cuda12.1.0-py310-torch2.1.2-tf2.14.0-1.12.0FROM $BASE_IMAGEWORKDIR /home/workspaceCOPY . /hom…

【论文阅读笔记】Learning to sample

Learning to sample 前沿引言方法问题声明S-NET匹配ProgressiveNet: sampling as ordering 实验分类检索重建 结论附录 前沿 这是一篇比较经典的基于深度学习的点云下采样方法 核心创新点&#xff1a; 首次提出了一种学习驱动的、任务特定的点云采样方法引入了两种采样网络&…