华为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. 区间元素均为数字,不考虑字母、符号等异常输入。
  2. 单个区间认定为无公共区间。

用例

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. 两两组合求出公共区间,左右分别相比,谁小取谁,删除重复的公共区间 [1,3][3,3][3,5]
  2. 有交集就合并,没交集就直接输出,左边谁小取谁,右边谁大取谁 [1,5]

2、具体步骤

  1. 第一行输入一个数字n,表示公共区间的数量;
  2. 接下来的n行,是具体的公共区间,并添加到集合list中;
  3. 两两组合求出公共区间,左右分别相比,谁小取谁,删除重复的公共区间;
    • 如果list就剩一个了,就不用比了;
    • 第一个数组 与 余下的数组进行两两比较;
    • 比较过的直接移除;
    • 遍历余下的数组;
      • 两个区间有交集;
      • 取交集,左取大,右取小;
      • 判断公共区间是否存在,如果不存在,加入到公共区间集合中;
    • 再取下一个第一个数组,再与余下的数组进行两两比较,循环往复;
  4. 有交集就合并,没交集就直接输出,左边谁小取谁,右边谁大取谁;
    • 如果list就剩一个了,就不用比了;
    • 第一个数组 与 余下的数组进行两两比较;
    • 此时不能直接删除,因为合并的才可以删除,不能合并的,直接输出即可;
    • 遍历余下的数组;
    • 当有交集时;
      • 左边谁小取谁,右边谁大取谁;
      • 删除有交集的区间;
      • 将合并后的区间加入到list,再进行比较合并;
      • 可以合并,重置mergeFlag为true,表示list中的数组还可以继续合并;
    • 如果当前比较的第一个数组,不能与余下的数组进行合并,将其删除;
      • 能与余下的数组进行合并的区间;
      • 可以合并,表示list中的数组还可以继续合并,重置合并表示为false;
    • 取第一个区间,与余下的区间进行合并,循环往复
  5. 按照左区间升序排序,如果相等,再按右区间升序排序;
  6. 将合并后的公共区间添加到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循环就可以解决了,确实简单了很多,找准方向才最重要~

核心思想没什么变化。

解题步骤也简化了很多。

  1. 第一行输入一个数字n,表示公共区间的数量;
  2. 接下来的n行,是具体的公共区间,并添加到集合list中;
  3. 按照左区间升序排序,如果相等,再按右区间升序排序;
  4. 定义公共区间集合publicRangeList;
  5. 遍历list,每一个数组与后面的数组分别比较,取交集;
    • 两个区间有交集,左右分别相比,取交集,左取大,右取小;
  6. 按照左区间升序排序,如果相等,再按右区间升序排序;
  7. 定义合并后的区间数组builder;
  8. 获取第一个有效的合并区间mergeArr;
  9. 遍历公共区间集合publicRangeList;
    • 有交集,取右区间的最大值;
    • 没有交集,拼接到合并的区间数组builder中;
    • 重置有效的合并区间为下一个区间;
  10. 输出合并后的区间数组即可。
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在线答疑。

在这里插入图片描述

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

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

相关文章

Screen记录窗口输出日志

screen是Linux窗口管理器&#xff0c;用户可以建立多个screen会话&#xff0c;每个screen会话又可以建立多个window窗口&#xff0c;每一个窗口就像一个可操作的真实的ssh终端一样。 screen详解&#xff1a;http://www.linuxidc.com/Linux/2013-10/91612.htm Linux Screen超简…

C++_动态二维数组的两种方法

介绍 本文主要介绍使用 动态二维数组的两种方法 (PS:仅作创建 动态二维数组参考,详细使用方法根据需求自行改变) 第一种&#xff1a;连续存储结构的 二维动态数组(需固定 列 大小&#xff0c;可通过下标访问) 缺点: 1.需要在设计二维数组前写死 列 的大小 2.空间利用率不高 优点…

PostgreSQL使用docker部署,设置密码失效问题处理

文章目录 问题描述使用场景排查解决修改已有的文件卷使用SQL初始化 问题描述 PostgreSQL使用docker虚拟化部署&#xff0c;使用docker-compose管理&#xff0c;配置了密码部署在客户现场时&#xff0c;客户的安全扫描&#xff0c;反馈测到PostgreSQL数据库弱密码漏洞查看docke…

神经网络学习小记录76——Tensorflow2设置随机种子Seed来保证训练结果唯一

神经网络学习小记录76——Tensorflow2设置随机种子Seed来保证训练结果唯一 学习前言为什么每次训练结果不同什么是随机种子训练中设置随机种子 学习前言 好多同学每次训练结果不同&#xff0c;最大的指标可能会差到3-4%这样&#xff0c;这是因为随机种子没有设定导致的&#x…

网络安全:专科及普通本科的温柔乡

当代普通大学生的现状是卷又卷不过、躺又躺不平&#xff0c;把大把的青春都荒废在了思考我应该做什么才能有前途的问题上面。当然&#xff0c;这里说的是那些普通学历且对自己的职业生涯甚至是人生没有规划的大学生&#xff0c;包括专科、普通一本二本&#xff0c;并非985、211…

MySQL-2

复习 1. Data数据–>DB数据库–>DBMS数据库管理系统常见DBMS: MySQL oracle sql server db2 … redis Mongodb两大功能&#xff1a; 定义DDL 操纵DML 2. 表table创建表, 行和列 3. MySQL数据类型数据类型分成三大类&#xff1a;数值型、字符型、日期时间类4. 关于列属性…

【JVM基础】 JVM 如何加载一个类以及类加载机制

文章目录 1、什么时候一个类会被加载&#xff1f;1、包含 main 方法的主类2、非 包含 main 方法的主类&#xff0c;什么时候去加载&#xff1f; 3、类加载器如何加载一个类&#xff1f;1、验证阶段&#xff1a;2、准备阶段&#xff1a;3、解析阶段&#xff1a;4、初始化&#x…

PHP开发日志——循环和条件语句嵌套不同,效率不同(循环内加入条件语句,条件语句判断后加入循环,array_map函数中加入条件语句)

十多年前开发框架时&#xff0c;为了效率不断试过各种代码写法&#xff0c;今天又遇到了&#xff0c;想想php8时代会不会有所变化&#xff0c;结果其实也还是和当年一样&#xff0c;但当年没写博客&#xff0c;但现在可以把数据记录下来了。 PHP_loop_ireflies_dark_forest 项目…

20231220将NanoPC-T4(RK3399)开发板的Android10的SDK按照Rockchip官方挖掘机开发板编译打包刷机之后启动跑飞

20231220将NanoPC-T4(RK3399)开发板的Android10的SDK按照Rockchip官方挖掘机开发板编译打包刷机之后启动跑飞 2023/12/20 17:19 简略步骤&#xff1a;rootrootrootroot-X99-Turbo:~/3TB$ tar --use-compress-programpigz -xvpf rk3399-android-10.git-20210201.tgz rootrootro…

递归算法:二叉树前序、中序、后序遍历解析与递归思想深度剖析

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《linux深造日志》 《高效算法》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 一、二叉树的遍历1.1 链式结构二叉树的创建1.1 二叉树结构图 二、 前序遍历代码演示&#xff1a;2.1 前序遍历递…

苏宁易购商品详情API:电商实时数据

一、引言 在当前的电商行业中&#xff0c;数据是最为宝贵的资源之一。如何获取实时、准确的数据&#xff0c;对于电商业务的运营和优化至关重要。作为中国领先的电商平台之一&#xff0c;苏宁易购提供了丰富的API接口&#xff0c;其中包括商品详情API&#xff0c;以便第三方开…

STL stack练习

CSTL之stack栈容器 - 数据结构教程 - C语言网CSTL之stack栈容器1.再谈栈回顾一下之前所学的栈&#xff0c;栈是一种先进后出的数据结构&#xff0c;而实现方式需要创建多个结构体&#xff0c;通过链式的方式进行实现&#xff0c;这是标准的栈的思路&#xff0c;而在STL中栈可以…

一键在线获取APP公钥、包名、签名及备案信息方法介绍

​ 目录 一键在线获取APP公钥、包名、签名及备案信息方法介绍 摘要 引言 一键获取APP包信息 操作步骤 ​编辑 解析报告 总结 致谢 关键词 参考资料 声明 摘要 本文介绍了一款在线APP解析工具&#xff0c;可以一键获取APP的公钥、包名、签名等基础信息&#xff0c;…

Python教程:对于初学者,几个易懂的装饰器示例用法

装饰器是Python中的一个高级功能&#xff0c;它可以用来扩展或修改一个函数或方法的功能&#xff0c;而不需要修改其原始代码。装饰器本质上是一个函数&#xff0c;它接受一个函数作为参数&#xff0c;并返回一个新的函数对象。 装饰器通常用于添加与函数功能无关的额外功能&a…

LeetCode 647回文子串 517最长回文子序列 | 代码随想录25期训练营day57

动态规划算法14 LeetCode 647 回文子串 2023.12.20 题目链接代码随想录讲解[链接] int countSubstrings(string s) {//暴力搜索&#xff0c;前两层遍历确定子字符串的起始和末尾位置//第三层循环判断当前子字符串是否为回文串/*int result 0;for (int i 0; i < s.size…

灰盒测试简要学习指南!

在本文中&#xff0c;我们将了解什么是灰盒测试、以及为什么要使用它&#xff0c;以及它的优缺点。 在软件测试中&#xff0c;灰盒测试是一种有用的技术&#xff0c;可以确保发布的软件是高性能的、安全的并满足预期用户的需求。这是一种从外部测试应用程序同时跟踪其内部操作…

2023 英特尔On技术创新大会直播 | 窥探未来科技的边界

2023 英特尔On技术创新大会直播 | 窥探未来科技的边界 写在最前面观后感其他有趣的专题课程 写在最前面 嘿&#xff0c;你是不是对科技和创新充满好奇&#xff1f;2023 英特尔 On 技术创新大会线上活动邀请你一起探索最前沿的科技世界&#xff01; 这不仅是一场普通的聚会&…

程序员的23大IONIO面试问题及答案

文章目录 1. 什么是IO流&#xff1f;2.java中有几种类型的流&#xff1f;3.字节流和字符流哪个好&#xff1f;怎么选择&#xff1f;4.读取数据量大的文件时&#xff0c;速度会很慢&#xff0c;如何选择流&#xff1f;5. IO模型有几种&#xff1f;6.阻塞IO &#xff08;blocking…

如何用Excel制作一张能在网上浏览的动态数据报表

前言 如今各类BI产品大行其道&#xff0c;“数据可视化”成为一个热门词汇。相比价格高昂的各种BI软件&#xff0c;用Excel来制作动态报表就更加经济便捷。今天小编就将为大家介绍一下如何使用葡萄城公司的纯前端表格控件——SpreadJS来实现一个Excel动态报表&#xff1a; 实…

华为鸿蒙操作系统简介及系统架构分析(2)

接前一篇文章&#xff1a;华为鸿蒙操作系统简介及系统架构分析&#xff08;1&#xff09; 本文部分内容参考&#xff1a; 鸿蒙系统学习笔记(一) 鸿蒙系统介绍 特此致谢&#xff01; 上一回对于华为的鸿蒙操作系统&#xff08;HarmonyOS&#xff09;进行了介绍并说明了其层次化…