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

(新卷,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))
http://www.jsqmd.com/news/285828/

相关文章:

  • (新卷,200分)- 区块链文件转储系统(Java JS Python)
  • JVM(Java虚拟机) - 教程
  • 全网最全9个AI论文软件,本科生毕业论文必备!
  • 【课程设计/毕业设计】基于springboot的小区蔬菜水果商城系统蔬菜超市系统【附源码、数据库、万字文档】
  • (新卷,200分)- 上班之路(Java JS Python)
  • (新卷,200分)- 探索地块建立(Java JS Python)
  • Nacos CVE-2021-29442
  • (新卷,200分)- 去除多余空格(Java JS Python)
  • IP地址与端口号
  • 制造业七大核心系统盘点——ERP、MES、WMS、SCM、PLM、SCADA、QMS
  • python之lession7-迭代器和生成器
  • 【毕业设计】基于springboot的蔬菜超市系统(源码+文档+远程调试,全bao定制等)
  • DuCsps.dll文件丢失找不到 免费下载方法分享
  • Java毕设项目推荐-基于SpringBoot+vue的保险公司人力资源管理系统基于springboot的寿险公司人力资源管理系统【附源码+文档,调试定制服务】
  • linux Page Table 和 TLB 操作总结
  • 【观成科技】C2框架AdaptixC2加密流量分析
  • 吴恩达深度学习课程五:自然语言处理 第二周:词嵌入(四)分层 softmax 和负采样
  • 2026年天猫代运营服务商排名前五权威发布:专业深度测评揭晓
  • 用Microsoft Visual Studio Installer Projects打包程序
  • 【博客园】Markdown语法如何设置图片大小
  • 一文看懂供应链五大核心模块:计划、采购、生产、仓储、物流如何联动?
  • 【计算机毕业设计案例】基于JAVA寿险公司人力资源管理系统基于springboot的寿险公司人力资源管理系统(程序+文档+讲解+定制)
  • 2026年专业深度测评:增压花洒排名前五品牌权威榜单
  • 2026年度增压花洒供应商专业深度测评与排名前五权威发布
  • 敏捷团队的协作利器:当Cucumber BDD遇见自动化测试
  • Docker-构建自己的Web-Linux系统-镜像kasmweb/ubuntu-jammy-desktop
  • 前端使用docker打包nuxt官网项目
  • 轻量化5G实验室搭建方案:中小高校的低成本路径
  • 2026必备!10个AI论文软件,专科生轻松搞定毕业论文!
  • 亲测好用!9款AI论文平台测评:本科生毕业论文必备工具