当前位置: 首页 > news >正文

凌乱的yyy / 线段覆盖

这是经典的区间调度问题,最优解法是贪心算法
1. 核心策略:优先选择结束时间最早的比赛,这样能留出更多时间给后续比赛,从而参加最多场次。
2. 步骤:

  • 将所有比赛按结束时间升序排序;
  • 遍历排序后的比赛,每次选择开始时间 ≥ 上一场比赛结束时间的比赛,计数 + 1。

为什么按结束时间排序?

  • 如果我们按开始时间排序,一个很早开始但持续很久的比赛会浪费掉后面很多场短比赛
  • 如果我们按持续时间排序,也可能因为位置尴尬而导致无法连接前后比赛
  • 按结束时间排序能为后面留出尽可能多的时间,从而容纳更多的比赛。

代码块解释

// 比赛实体类,存储开始和结束时间
class Game implements Comparable<Game> {int start;int end;public Game(int start, int end) {this.start = start;this.end = end;}// 按结束时间升序排序(贪心核心)@Overridepublic int compareTo(Game o) {return this.end - o.end;}
}
  • Comparable< Game >:让你的Game类具备“可比较”的能力
  • comparaTo(Game o):定义怎么比较(按结束时间从小到大排)

它们的唯一目的:
让Arrays(games)能正确给比赛按结束时间排序

① Comparable 接口
这句话的意思:
我这个 Game 类(比赛),可以和另一个 Game 比较大小。
是泛型,意思是:
只和 Game 比,不和别的类比

② compareTo 方法(必须重写)

@Override
public int compareTo(Game o) {return this.end - o.end;
}

这个方法的规则(固定死的)

  • 返回负数:当前对象排在前面
  • 返回正数:当前对象排在后面
  • 返回0:两个对象相等

套在我们的代码里
this.end -> 当前比赛的结束时间
o.end -> 另一个比赛的结束时间
return this.end - o.end
= 按结束时间从小到大排序

1. Comparable 和 Comparator 的区别?

接口 含义 用法 比喻
Comparable 自己和别人比 写在类里面 自己自带 “比较规则”
Comparator 找个裁判来比 写在类外面 单独弄个 “比较器”

2. 为什么不用 Comparator?
不是不能用!是没必要,而且前者更简洁。

3. Comparable 和 Comparator 的使用场景

  1. 类有 “默认排序规则” → 用 Comparable
    比如:比赛永远按结束时间排序,这是它的天然规则。
  2. 临时需要换一种排序 → 用 Comparator
    比如:这次按结束时间,下次按开始时间。

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
一句话翻译
这是 Java 里最快、最适合读大量数据的键盘输入工具
专门用来读题目里的输入数据(比如 n、比赛时间)。

拆开讲
1. System.in

  • 意思:键盘输入
  • 作用:代表 “从键盘 / 控制台读数据”
  • 它是字节流,不能直接读文字,必须包装。

2. InputStreamReader

  • 作用:把字节流 → 转换成字符流
  • 翻译:把键盘的信号变成 Java 能看懂的文字

3. BufferedReader

  • 核心!
  • 作用:带缓冲区的快速读取器
  • 好处:读得飞快,比 Scanner 快 10~100 倍
  • 题目数据量大(n=1e6)必须用它,否则会超时!

整体理解(生活比喻)

  • System.in = 自来水龙头(原始水源)
  • InputStreamReader = 转接头
  • BufferedReader = 大水缸(缓冲,一次读一大桶,超快

这一行 = 组装一个 “快速读入水管”

方式 速度 适合场景
BufferedReader 极快 大数据(题目 100% 数据)
Scanner 小数据、初学练习

这道题 n 最大 100 万,必须用 BufferedReader,Scanner 会超时。

常用方法

// 读一整行文字(比如读 n,读比赛时间)
br.readLine();// 转成数字
int n = Integer.parseInt(br.readLine());
  1. br.readLine() 读出来永远是字符串,也就是文本
    比如你输入3,br.readLine()拿到的是:"3" ,它只是字符文本,不能做加减乘除,不能做数组下标

2. Integer.parseInt(字符串) 干什么?
作用:把数字格式的字符串,转成真正的 int 整数
举例:

  • "3" 字符串 → 转成 整数 3
  • "123" 字符串 → 转成 整数 123

执行流程:

  1. br.readLine() 读取一行输入 → 得到字符串 "3"
  2. Integer.parseInt("3") → 转换成数字 3
  3. 把数字 3 赋值给 int n
// 读取所有比赛时间
for (int i = 0; i < n; i++) {String[] line = br.readLine().split(" ");int s = Integer.parseInt(line[0]);int e = Integer.parseInt(line[1]);games[i] = new Game(s, e);
}

一句话总结
循环n次,把每一行输入的两个比赛时间读进来,变成比赛对象,存进数组里

逐行拆解
1. for (int i = 0; i < n; i++)

  • 作用:循环 n 次
  • 因为一共有 n 场比赛,所以要读 n 行数据

2. br.readLine()

  • 读取一整行输入
  • 比如输入:0 2
  • 读到的是字符串:"0 2"

3. .split(" ")

  • 空格把这一行切开
  • "0 2" → 切成 ["0", "2"]
  • 结果存进 String[] line 数组

4. String[] line = ...

  • line 是一个字符串数组
  • line[0] = 第一个数 "0"
  • line[1] = 第二个数 "2"

5. int s = Integer.parseInt(line[0]);

  • 字符串 "0"变成数字 0
  • 存到变量 s(start 开始时间)

6. int e = Integer.parseInt(line[1]);

  • 字符串 "2"变成数字 2
  • 存到变量 e(end 结束时间)

7. games[i] = new Game(s, e);

  • 创建一个比赛对象
  • 把开始时间 s、结束时间 e 放进去
  • 存进数组 games 的第 i 个位置

完整Java代码实现如下

import java.io.*;
import java.util.Arrays;// 比赛实体类,存储开始和结束时间
class Game implements Comparable<Game> {int start;int end;public Game(int start, int end) {this.start = start;this.end = end;}// 按结束时间升序排序(贪心核心)@Overridepublic int compareTo(Game o) {return this.end - o.end;}
}public class Main {public static void main(String[] args) throws IOException {// 快速输入输出(应对 n=1e6 的大数据量)BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine());Game[] games = new Game[n];// 读取所有比赛时间for (int i = 0; i < n; i++) {String[] line = br.readLine().split(" ");int s = Integer.parseInt(line[0]);int e = Integer.parseInt(line[1]);games[i] = new Game(s, e);}// 按结束时间排序Arrays.sort(games);int count = 0;      // 最多参加的比赛数int lastEnd = -1;   // 上一场比赛的结束时间(初始为-1,保证第一场能选)// 贪心遍历for (Game game : games) {if (game.start >= lastEnd) {count++;lastEnd = game.end;}}System.out.println(count);}
}
http://www.jsqmd.com/news/795586/

相关文章:

  • openclaw官网入口是什么_本地部署官网版龙虾AI的详细步骤(免费使用)
  • 自建AI编程助手服务:Recodex部署与Codex API代理实战
  • 1、Chrome Elements面板:从入门到精通的网页调试实战指南
  • 沃尔玛回收怎么不踩坑?老用户分享闲置购物卡变现经验 - 喵权益卡劵助手
  • 终极解决方案:如何用VisualCppRedist AIO一键修复所有VC++运行库问题
  • ABAQUS结果导出避坑指南:如何精准提取指定截面节点的应力应变数据到TXT
  • MATLAB处理SMAP土壤水HDF5数据:从读取到生成GeoTIFF的完整流程(附代码)
  • Proteus仿真串口调试太麻烦?试试用Virtual Terminal虚拟终端一键搞定(附Arduino/51单片机配置)
  • 2026年贵阳室内装修全案设计深度横评:从设计落地率到质保体系的完全选购指南 - 企业名录优选推荐
  • 不止于安装:用Armadillo库的5个高效函数,让你的C++矩阵操作代码量减半
  • League Akari终极指南:英雄联盟玩家的智能游戏助手完整教程
  • 2026年贵阳室内装修全案设计深度横评:从设计落地到透明整装的完整选购指南 - 企业名录优选推荐
  • AI架构绘图副驾驶:用自然语言生成专业Excalidraw架构图
  • 医学语义分割类-基于UPerNet模型的视网膜血管语义分割 深度学习医学图像处理 视觉眼睛视网膜血管语义分割
  • 暗黑破坏神2存档修改终极指南:5分钟掌握免费d2s-editor
  • 2026重庆口碑好的装修公司推荐,业主真实评价出炉 - 大渝测评
  • 晋中门店引流与私域转化|新思域科技手机号定向推广系统深度评测 - 优质企业观察收录
  • 别再手动敲命令了!用Shell的Here Document(EOF)自动化你的SFTP/MySQL登录操作
  • RSA密钥管理实战:从生成、存储到安全分发的全流程解析
  • 2026最新护理/计算机应用/机电应用技术/铁道运输/新能源汽车制造与检测学校推荐!湖南优质权威榜单发布,实力靠谱衡阳中职学校精选 - 十大品牌榜
  • 别再只当Atlas是元数据仓库了!手把手教你用它的分类和术语表,像管理图书馆一样治理数据
  • 告别数据孤岛:手把手教你用Matlab和OpenSim 4.1搞定C3D到TRC的格式转换(附环境配置避坑指南)
  • Cursor Pro自动化工具:跨平台GUI实现与机器码重置技术解析
  • 2026年晋中手机号定向推广与GEO优化破局指南:新思域科技精准获客系统深度评测 - 优质企业观察收录
  • 8086/8088单板机VSCode集中环境开发编译(第二版整理)
  • 2026年简易操作安装Hermes Agent/OpenClaw Token Plan全流程解析大全集全解
  • 2026年贵阳室内装修全案设计深度横评:从设计落地到透明整装的一站式避坑指南 - 企业名录优选推荐
  • Python自动化脚本开发:闲鱼商品管理与消息自动回复技术解析
  • 2026年山西精准获客与GEO优化深度破局指南:手机号定向推广如何拯救中小企业高成本获客困局 - 优质企业观察收录
  • 从TSP到神经网络调参:遗传算子选不对,优化效果差十倍!