华为OD机试 - 区间交集 - 深度优先搜索dfs算法(滥用)(Java 2023 B卷 200分)

目录
- 专栏导读
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 备注
- 用例
- 1、输入
- 2、输出
- 3、说明
- 四、解题思路
- 1、核心思路:
- 2、具体步骤
- 五、Java算法源码
- 再重新读一遍题目,看看能否优化一下~
- 解题步骤也简化了很多。
- 六、效果展示
- 1、输入
- 2、输出
- 3、说明
华为OD机试 2023B卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
给定一组闭区间,其中部分区间存在交集。
任意两个给定区间的交集,称为公共区间(如:[1,2],[2,3]的公共区间为[2,2],[3,5],[3,6]的公共区间为[3,5])公共区间之间若存在交集,则需要合并(如:[1,3],[3,5]区间存在交集[3,3],需合并为[1,5])。按升序排列输出合并后的区间列表。
二、输入描述
组区间列表
区间数为 N: O<=N<=1000。
区间元素为 X:-10000<=X<=10000。
三、输出描述
升序排列的合并区间列表
备注
- 区间元素均为数字,不考虑字母、符号等异常输入。
- 单个区间认定为无公共区间。
用例
1、输入
4
0 3
1 3
3 5
3 6
2、输出
[1,5]
3、说明
- 0 3和1 3的公共区间是1 3
- 0 3和3 5的公共区间是3 3
- 0 3和3 6的公共区间是3 3
- 1 3和3 5的公共区间是3 3
- 1 3和3 6的公共区间是3 3
- 3 5和3 6的公共区间是3 5
- 两两组合求出公共区间,去重,变为[1,3][3,3][3,5]
- 若公共区间存在交集,合并为[1,5]
四、解题思路
第一反应是通过深度优先搜索dfs算法来解。
1、核心思路:
- 两两组合求出公共区间,左右分别相比,谁小取谁,删除重复的公共区间 [1,3][3,3][3,5]
- 有交集就合并,没交集就直接输出,左边谁小取谁,右边谁大取谁 [1,5]
2、具体步骤
- 第一行输入一个数字n,表示公共区间的数量;
- 接下来的n行,是具体的公共区间,并添加到集合list中;
- 两两组合求出公共区间,左右分别相比,谁小取谁,删除重复的公共区间;
- 如果list就剩一个了,就不用比了;
- 第一个数组 与 余下的数组进行两两比较;
- 比较过的直接移除;
- 遍历余下的数组;
- 两个区间有交集;
- 取交集,左取大,右取小;
- 判断公共区间是否存在,如果不存在,加入到公共区间集合中;
- 再取下一个第一个数组,再与余下的数组进行两两比较,循环往复;
- 有交集就合并,没交集就直接输出,左边谁小取谁,右边谁大取谁;
- 如果list就剩一个了,就不用比了;
- 第一个数组 与 余下的数组进行两两比较;
- 此时不能直接删除,因为合并的才可以删除,不能合并的,直接输出即可;
- 遍历余下的数组;
- 当有交集时;
- 左边谁小取谁,右边谁大取谁;
- 删除有交集的区间;
- 将合并后的区间加入到list,再进行比较合并;
- 可以合并,重置mergeFlag为true,表示list中的数组还可以继续合并;
- 如果当前比较的第一个数组,不能与余下的数组进行合并,将其删除;
- 能与余下的数组进行合并的区间;
- 可以合并,表示list中的数组还可以继续合并,重置合并表示为false;
- 取第一个区间,与余下的区间进行合并,循环往复
- 按照左区间升序排序,如果相等,再按右区间升序排序;
- 将合并后的公共区间添加到builder中,输出即可。
五、Java算法源码
public class OdTest07 {// 公共区间集合static List<int[]> publicRangeList = new ArrayList<>();public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = Integer.valueOf(sc.nextLine());List<int[]> list = new ArrayList<>();for (int i = 0; i < n; i++) {int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();list.add(arr);}// 两两组合求出公共区间,左右分别相比,谁小取谁,删除重复的公共区间 [1,3][3,3][3,5]dfs(list);// 有交集就合并,没交集就直接输出,左边谁小取谁,右边谁大取谁 [1,5]mergeDfs(publicRangeList);publicRangeList.addAll(unMergeList);// 按照左区间升序排序,如果相等,再按右区间升序排序publicRangeList.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);StringBuilder builder = new StringBuilder();for (int i = 0; i < publicRangeList.size(); i++) {builder.append(publicRangeList.get(i)[0]).append(" ").append(publicRangeList.get(i)[1]).append("\n");}System.out.println(builder.deleteCharAt(builder.length() - 1));}// 两两组合求出公共区间private static void dfs(List<int[]> list) {// 如果list就剩一个了,就不用比了if (list.size() == 1) {return;}// 第一个数组 与 余下的数组进行两两比较int[] firstArr = list.get(0);int left = firstArr[0];int right = firstArr[1];// 比较过的直接移除list.remove(0);// 余下的数组for (int i = 0; i < list.size(); i++) {// 余下的数组int[] comareArr = list.get(i);// 两个区间有交集if (right >= comareArr[0] && comareArr[1] >= left) {// 取交集,左取大,右取小int compareLeft = left <= comareArr[0] ? comareArr[0] : left;int compareRight = right <= comareArr[1] ? right : comareArr[1];int[] range = new int[]{compareLeft, compareRight};// 判断公共区间是否存在,如果不存在,加入到公共区间集合中if (!compareArr(range)) {publicRangeList.add(range);}}}// 再取下一个第一个数组,再与余下的数组进行两两比较,循环往复dfs(list);}// 判断公共区间是否存在private static boolean compareArr(int[] arr) {for (int i = 0; i < publicRangeList.size(); i++) {int[] rangeArr = publicRangeList.get(i);if (arr[0] == rangeArr[0] && arr[1] == rangeArr[1]) {return true;}}return false;}// 是否可以合并static boolean mergeFlag = false;// 不能合并的数组区间static List<int[]> unMergeList = new ArrayList<>();// 有交集就合并,没交集就直接输出,左边谁小取谁,右边谁大取谁private static void mergeDfs(List<int[]> list) {// 如果list就剩一个了,就不用比了if (list.size() == 1) {return;}// 第一个数组 与 余下的数组进行两两比较// [3,6][5,6][5,7][6,6][6,7][6,8][9,10]int[] firstArr = list.get(0);int left = firstArr[0];int right = firstArr[1];// 此时不能直接删除,因为合并的才可以删除,不能合并的,直接输出即可// 余下的数组for (int i = 1; i < list.size(); i++) {int[] comareArr = list.get(i);// [9,10][3,6][5,7][6,8]// 当有交集时if (right >= comareArr[0] && comareArr[1] >= left) {// 左边谁小取谁,右边谁大取谁int compareLeft = left <= comareArr[0] ? left : comareArr[0];int compareRight = right <= comareArr[1] ? comareArr[1] : right;int[] range = new int[]{compareLeft, compareRight};// 删除有交集的区间list.remove(firstArr);list.remove(comareArr);// 将合并后的区间加入到list,再进行比较合并list.add(range);// 可以合并,表示list中的数组还可以继续合并mergeFlag = true;break;}}// 如果当前比较的第一个数组,不能与余下的数组进行合并,将其删除if (!mergeFlag) {list.remove(firstArr);// 能与余下的数组进行合并的区间unMergeList.add(firstArr);} else {// 可以合并,表示list中的数组还可以继续合并// 重置合并表示为falsemergeFlag = false;}// 取第一个区间,与余下的区间进行合并,循环往复mergeDfs(list);}
}
感觉这道题,不至于这么复杂吧。
再重新读一遍题目,看看能否优化一下~
因为最近一直在刷dfs的算法题,所以第一反应是采用dfs来解,不过,普通的for循环就可以解决了,确实简单了很多,找准方向才最重要~
核心思想没什么变化。
解题步骤也简化了很多。
- 第一行输入一个数字n,表示公共区间的数量;
- 接下来的n行,是具体的公共区间,并添加到集合list中;
- 按照左区间升序排序,如果相等,再按右区间升序排序;
- 定义公共区间集合publicRangeList;
- 遍历list,每一个数组与后面的数组分别比较,取交集;
- 两个区间有交集,左右分别相比,取交集,左取大,右取小;
- 按照左区间升序排序,如果相等,再按右区间升序排序;
- 定义合并后的区间数组builder;
- 获取第一个有效的合并区间mergeArr;
- 遍历公共区间集合publicRangeList;
- 有交集,取右区间的最大值;
- 没有交集,拼接到合并的区间数组builder中;
- 重置有效的合并区间为下一个区间;
- 输出合并后的区间数组即可。
public class OdTest07 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = Integer.valueOf(sc.nextLine());List<int[]> list = new ArrayList<>();for (int i = 0; i < n; i++) {int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();list.add(arr);}// 按照左区间升序排序,如果相等,再按右区间升序排序list.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);// 公共区间集合List<int[]> publicRangeList = new ArrayList<>();// 遍历list,每一个数组与后面的数组分别比较,取交集for (int i = 0; i < list.size(); i++) {int[] arr = list.get(i);for (int j = i + 1; j < list.size(); j++) {int[] nextArr = list.get(j);// 两个区间有交集if (arr[1] >= nextArr[0]) {// 左右分别相比,取交集,左取大,右取小publicRangeList.add(new int[]{Math.max(arr[0], nextArr[0]), Math.min(arr[1], nextArr[1])});}}}// [3,6][5,6][6,6][5,7][6,8][6,7][9,10]if (publicRangeList.size() == 0) {System.out.println("None");return;}// [3,6][5,6][5,7][6,6][6,7][6,8][9,10]publicRangeList.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);// 合并后的区间数组StringBuilder builder = new StringBuilder();// 有效的合并区间int[] mergeArr = publicRangeList.get(0);for (int i = 1; i < publicRangeList.size(); i++) {int[] nextArr = publicRangeList.get(i);// 有交集,取右区间的最大值if (mergeArr[1] >= nextArr[0]) {mergeArr[1] = Math.max(mergeArr[1], nextArr[1]);} else {// 没有交集,拼接到合并的区间数组builder中builder.append(mergeArr[0]).append(" ").append(mergeArr[1]).append("\n");// 重置有效的合并区间为下一个区间mergeArr = nextArr;}}builder.append(mergeArr[0]).append(" ").append(mergeArr[1]).append("\n");// 输出合并后的区间数组System.out.println(builder.deleteCharAt(builder.length() - 1));}
}
六、效果展示
1、输入
5
9 10
5 7
6 11
3 8
3 6
2、输出
3 8
9 10
3、说明
- 3 6和3 8的公共区间是3 6
- 3 6和5 7的公共区间是5 6
- 3 6和6 11的公共区间是6 6
- 3 6和9 10的公共区间是无
- 3 8和5 7的公共区间是5 7
- 3 8和6 11的公共区间是6 8
- 3 8和9 10的公共区间是无
- 5 7和6 11的公共区间是6 7
- 5 7和9 10的公共区间是无
- 6 11和9 10的公共区间是9 10
- 两两组合求出公共区间:[3,6][5,6][6,6][5,7][6,8][6,7][9,10]
- 有交集就合并,没交集就直接输出:[3,8][9,10]

🏆下一篇:华为OD机试 - 最长的顺子 - 感谢@禁止你发言提供的更简便算法(Java 2023 B卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

相关文章:
华为OD机试 - 区间交集 - 深度优先搜索dfs算法(滥用)(Java 2023 B卷 200分)
目录 专栏导读一、题目描述二、输入描述三、输出描述备注用例1、输入2、输出3、说明 四、解题思路1、核心思路:2、具体步骤 五、Java算法源码再重新读一遍题目,看看能否优化一下~解题步骤也简化了很多。 六、效果展示1、输入2、输出3、说明 华为OD机试 2…...
德人合科技 | 防止公司电脑文件数据资料外泄,自动智能透明加密保护系统
【透明加密软件】——防止公司电脑文件数据资料防止外泄,自动智能透明加密保护内部核心文件、文档、图纸、源代码、音视频等资料! PC端访问地址: www.drhchina.com 🌟 核心功能: 透明加密:采用高级加密算…...
常见加解密算法分析(含使用场景)
加密算法主要分为三类:对称加密算法、非对称加密算法和散列算法。下面将分别介绍这些类别中的常见算法及其特点和使用场景。 对称加密算法 1. AES (Advanced Encryption Standard) 简介: AES是一种广泛使用的对称加密标准,可以使用128、19…...
Oracle基本的SQL语句
1.最基本的增删改查 1.1.新增 insert 1.1.1.单表新增 INSERT INTO table_count_output (data_date,table_name,table_count ) VALUES (2023-03-15,FMCUSLVL,351 );COMMIT; 1.1.2.关联新增 INSERT INTO table_count_output (data_date,table_name,table_count )SELECTdata_…...
golang项目目录推荐
序言 逛GitHub的时候发现有个4.5k对goalng项目结构的推荐的项目,这里就简单的推荐下 文件目录 /cmd 项目主要的应用程序。 对于每个应用程序来说这个目录的名字应该和项目可执行文件的名字相匹(例如,/cmd/myapp)。不要在这个…...
Maven scope属性解读和使用注意事项
目录 compile runtime test system provided import dependencyManagement标签介绍 maven的scope有哪些: maven的scope一共包括:compile、runtime、test、system、provided、import。 compile <dependency><groupId>org.apache.htt…...
Vue3使用 xx UI解决布局高度自适应
解决方案 在相应的Sider部分添加:height: ‘91.8vh’,即可。示例: <Layout><Sider hide-trigger :style"{background: #fff, height: 91.8vh}"> }知识补充 vw、vh、vmin、vmax是一种视窗单位,也是相对单…...
九牧:科技卫浴,长期主义
“没有做错什么,但却输给了时代”,这是人们给当年手机巨头诺基亚的注解。 谁也没有想到,曾在手机行业称雄的诺基亚,最终败给了时代。当年,在2G向3G、4G跨越的时候,苹果、微软的iOS和安卓系统将手机从简单的…...
中级软件设计师-note-2
一个逆向思维的例子是 “当遇到一个问题时,通常人们会想办法解决这个问题。但逆向思维是指反过来考虑,即想办法制造更多的问题。 举个例子,假设有一个团队正在开发一款新的智能手机。传统的思维方式可能是专注于如何增加手机的功能…...
解锁商业宝藏:迅软科技答疑保护商业秘密的重要性
商业秘密指不为公众所知悉、具有商业价值并经权利人采取相应保密措施的技术信息、经营信息等商业信息,一旦泄露可能会给公司带来极大的经济损失和竞争压力,保护商业秘密既能维护企业自身合法权益,也能保障市场经济长期健康发展需求。 保护商…...
【GIT】撤销命令
git add 撤销 add 错误文件,撤销掉add列表的文件使用: git reset [文件名] 撤销单个文件 git reset . 撤销全部 git commit 撤销 commit 之后,但是还没有push 可以用撤回刚刚的commit 记录 git reset HEAD~ git log -v 查看提交记录...
开发知识点-09Rust
Rust Rust 语言通常用于编写系统级软件、网络服务器和高性能应用程序,它具有以下特点:1. 高性能和内存安全:Rust 在保证高性能的同时,利用其所有权模型和借用检查器等特性确保内存安全,避免了 C/C 等语言的内存错误和崩…...
Android开发中,百度语音集成之一
我们在开发中,用到实时语音的时候,会有讯飞、百度、阿里,今天主要讲解的是百度语音之语音合成: public class YuYinUtil { private static final Logger logger LogManager.getLogger(YuYinUtil.class); public static final St…...
nodejs连接mongodb报错SyntaxError: Unexpected token .
nodejs连接mongodb报错SyntaxError: Unexpected token 如下图 经过排查,原因是npm默认安装的mongodb插件是最新版6.3.0 ,而mongodb数据库版本是4.0.0 ,两者版本不同导致nodejs报错。 解决方法是npm卸载新版本的mongodb插件,再安…...
Ubuntu 常用命令之 gunzip 命令用法介绍
📑Linux/Ubuntu 常用命令归类整理 gunzip是一个在Ubuntu系统下用于解压缩文件的命令。它主要用于解压.gz格式的文件。这个命令是gzip命令的反向操作,gzip用于压缩文件,而gunzip则用于解压缩文件。 gunzip命令的参数有 -c 或 --stdout 或 -…...
sun.misc.BASE64Encoder 进行maven打包时报错
报错如下: 报错代码,是因为引用了sun.misc.BASE64Decoder等类不属于JDK标准库范畴,但在JDK中包含了该类,可以直接使用。在jdk1.9中就不存在了。 import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder;BASE64Encoder enc…...
[DNS网络] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案
[网络故障] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案 问题描述 最近,我在使用CSDN插件浏览 MOOC 网站时,遇到了一些网络故障。具体表现为: MOOC 中国大学慕课网:www.icourse163.org点击CSDN插件首页的 MOOC(…...
CSS设计器的使用
目录 css的概念 css的优势 css的基本语法 html中引入css样式 CSS基本选择器 选择器的使用 初级选择器: 标签选择器 类选择器 id选择器 高级选择器(结构选择器) ①后代选择器(E F) ②子选择器(E>F) ③相邻兄弟选择器(EF) ④通用兄弟选择器(…...
3d渲染太慢怎么办?2024效果图云渲染AI加速来袭
在不断变革的数码技术世界中,三维渲染技术在影视制作、游戏开发以及建筑设计等多个领域得到了广泛运用。然而,高清质量的三维项目的离线渲染时间长久一直是困扰 CG 工作者的一大难题。通常来讲,渲染一帧画面可能需要几分钟到几小时࿰…...
指针函数函数指针回调函数相关知识
指针函数: 本质上是一个函数,返回值是一个指针类型;不能返回局部变量的地址,因为其所存储在栈区,在函数调用结束时,被OS回收了;可以返回的情况:全局变量的地址、static修饰的局部变…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
