news 2026/3/10 12:41:17

(新卷,200分)- 区间交叠问题(Java JS Python)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(新卷,200分)- 区间交叠问题(Java JS Python)

(新卷,200分)- 区间交叠问题(Java & JS & Python)

题目描述

给定坐标轴上的一组线段,线段的起点和终点均为整数并且长度不小于1,请你从中找到最少数量的线段,这些线段可以覆盖柱所有线段。

输入描述

第一行输入为所有线段的数量,不超过10000,后面每行表示一条线段,格式为"x,y",x和y分别表示起点和终点,取值范围是[-10^5,10^5]。

输出描述

最少线段数量,为正整数

用例
输入

3
1,4
2,5
3,6

输出2
说明
题目解析

用例1图示如下

可以发现,只要选择[]1,4[和[3,6]就可以覆盖住所有给定线段。

我的解题思路如下:

首先,将所有区间ranges按照开始位置升序。

然后,创建一个辅助的栈stack,初始时将排序后的第一个区间压入栈中。

然后,遍历出1~ranges.length范围内的每一个区间ranges[i],将遍历到ranges[i]和stack栈顶区间对比:

  • 如果stack栈顶区间可以包含ranges[i]区间,则range[i]不压入栈顶
  • 如果stack栈顶区间被ranges[i]区间包含,则弹出stack栈顶元素,继续比较ranges[i]和stack新的栈顶元素
  • 如果stack栈顶区间和ranges[i]无法互相包含,只有部分交集,则将ranges[i]区间去除交集部分后,剩余部分区间压入stack
  • 如果stack栈顶区间和ranges[i]区间没有交集,那么直接将ranges[i]压入栈顶

这样的话,最终stack中有多少个区间,就代表至少需要多少个区间才能覆盖所有线段。

比如,用例1的运行流程如下:

2,5 和 1,4 存在重叠区间,我们只保留2,5区间的非重叠部分4,5

比较4,5区间和3,6区间,发现3,6完全涵盖2,5,因此2,5区间不再需要,可以从stack中弹栈删掉,即原始的2,5区间被删除了。

继续比较1,4和3,6区间,发现无法互相涵盖,因此都需要保留,但是3,6有部分区间和1,4重叠,因此只保留3,6不重叠部分4,6。

最终只需要两个区间,对应1,4、3,6,即可涵盖所有线段

自测用例:

8
0,4
1,2
1,4
3,7
6,8
10,12
11,13
12,14

输出5,即至少需要上面标红的五个区间才能覆盖所有线段。


2023.01.27

根据网友指正,上面逻辑缺失一个场景,比如:

3

1,10

5,12

8,11

按找前面逻辑,首先对所有区间按开始位置升序,然后将1,10入栈

然后尝试将5,12入栈,发现和栈顶区间有交集,因此去除交集部分后,5,12变为10,12,入栈

然后尝试将8,11入栈,但是此时出现一个尴尬的情况,那就是栈顶区间10,12不能完全包含8,11,因此8,11区间还需要和栈顶前一个区间1,10继续比较,这就背离了我们一开始将所有区间按开始位置升序的初衷了。。。

而导致这个问题的根本原因是,栈顶区间10,12是被裁剪过的,因此导致它的起始位置落后了,即可能无法包含住升序后下一个区间的起始位置了,但是转念一想,先入栈的区间的起始位置肯定是要小于等于后入栈的区间的,因此栈顶区间被裁剪,说明栈顶区间和前一个区间必然是严密结合的,因此8,11的起始位置超出了栈顶区间,其实还是会被栈顶前一个区间包含进去。因此这里8,11不入栈。

JavaScript算法源码
/* JavaScript Node ACM模式 控制台输入获取 */ const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const lines = []; let n; rl.on("line", (line) => { lines.push(line); if (lines.length === 1) { n = lines[0] - 0; } if (n && lines.length === n + 1) { lines.shift(); const ranges = lines.map((line) => line.split(",").map(Number)); console.log(getResult(ranges, n)); lines.length = 0; } }); function getResult(ranges, n) { ranges.sort((a, b) => a[0] - b[0]); const stack = [ranges[0]]; for (let i = 1; i < ranges.length; i++) { const range = ranges[i]; while (true) { if (stack.length == 0) { stack.push(range); break; } const [s0, e0] = stack.at(-1); const [s1, e1] = range; if (s1 <= s0) { if (e1 <= s0) { break; } else if (e1 < e0) { break; } else { stack.pop(); } } else if (s1 < e0) { if (e1 <= e0) { break; } else { stack.push([e0, e1]); break; } } else { stack.push(range); break; } } } //console.log(stack); return stack.length; }
Java算法源码
import java.util.Arrays; import java.util.LinkedList; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = Integer.parseInt(sc.nextLine()); Integer[][] ranges = new Integer[n][]; for (int i = 0; i < n; i++) { ranges[i] = Arrays.stream(sc.nextLine().split(",")).map(Integer::parseInt).toArray(Integer[]::new); } System.out.println(getResult(ranges)); } public static int getResult(Integer[][] ranges) { Arrays.sort(ranges, (a, b) -> a[0] - b[0]); LinkedList<Integer[]> stack = new LinkedList<>(); stack.add(ranges[0]); for (int i = 1; i < ranges.length; i++) { Integer[] range = ranges[i]; while (true) { if (stack.size() == 0) { stack.add(range); break; } Integer[] top = stack.getLast(); int s0 = top[0]; int e0 = top[1]; int s1 = range[0]; int e1 = range[1]; if (s1 <= s0) { if (e1 <= s0) { break; } else if (e1 < e0) { break; } else { stack.removeLast(); } } else if (s1 < e0) { if (e1 <= e0) { break; } else { stack.add(new Integer[] {e0, e1}); break; } } else { stack.add(range); break; } } } return stack.size(); } }
Python算法源码
# 输入获取 n = int(input()) rans = [list(map(int, input().split(","))) for i in range(n)] # 算法入口 def getResult(rans, n): rans.sort(key=lambda x: x[0]) stack = [rans[0]] for i in range(1, n): ran = rans[i] while True: if len(stack) == 0: stack.append(ran) break s0, e0 = stack[-1] s1, e1 = ran if s1 <= s0: if e1 <= s0: break elif e1 < e0: break else: stack.pop() elif s1 < e0: if e1 <= e0: break else: stack.append([e0, e1]) break else: stack.append(ran) break return len(stack) # 算法调用 print(getResult(rans, n))
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/8 0:45:08

(新卷,200分)- 区块链文件转储系统(Java JS Python)

(新卷,200分)- 区块链文件转储系统&#xff08;Java & JS & Python&#xff09; 题目描述 区块链底层存储是一个链式文件系统&#xff0c;由顺序的N个文件组成&#xff0c;每个文件的大小不一&#xff0c;依次为F1,F2,...,Fn。随着时间的推移&#xff0c;所占存储会越…

作者头像 李华
网站建设 2026/3/3 8:52:06

制造业七大核心系统盘点——ERP、MES、WMS、SCM、PLM、SCADA、QMS

我这几年跑工厂、聊老板、跟信息化负责人沟通&#xff0c;听到最多的一句话不是我们没系统&#xff0c;而是&#xff1a;ERP 上了&#xff0c;车间还是一团乱MES 买了&#xff0c;数据没人信仓库有系统&#xff0c;库存还是对不上系统一堆&#xff0c;但问题一个没少这时候很多…

作者头像 李华
网站建设 2026/3/4 21:49:04

前端使用docker打包nuxt官网项目

安装docker的文章在另一篇&#xff1a;https://blog.csdn.net/m0_69727853/article/details/154741168?spm1001.2014.3001.5501 1. 查看docker是否安装成功 docker -v 2. 如果显示没有docker&#xff0c;查看当前的环境变量是否正确 tips提示&#xff1a;如果找不到安装的doc…

作者头像 李华
网站建设 2026/3/5 17:18:33

Java计算机毕设之基于Java+springboot的寿险公司人力资源管理系统基于SpringBoot的人力资源管理系统(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/3/3 21:22:22

PolarDB-X 企业版分布式集群部署文档

目录PolarDB-X 企业版分布式集群部署文档快速连接快速连接命令集群信息集群状态Pod 列表服务列表镜像版本安装步骤1. 安装 Helm2. 创建命名空间3. 添加 Helm 仓库并安装 Operator4. 获取最新镜像版本5. 创建集群配置文件6. 部署集群7. 监控部署进度8. 获取连接密码集群架构架构…

作者头像 李华
网站建设 2026/3/1 23:18:42

计算机Java毕设实战-基于springboot的社区协作与资源共享系统社区闲置资源交易与共享系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华