华为OD机考算法题:最小数量线段覆盖

目录

题目部分

解读与分析

代码实现


题目部分

题目最小数量线段覆盖
难度
题目说明给定坐标轴(一维坐标轴)上的一组线段,线段的起点和终点均为整数并且长度不小于1,请你从中找到最少数量的线段,这些线段可以覆盖住所有线段。
输入描述第一行输入为所有线段的数量,不超过 10000,后面每行表示一条线段,格式为”x,y",x 和 y 分别表示起点和终点,取值范围是 [-10^{5},10^{5}]。
输出描述最少线段数量,为正整数。
补充说明
------------------------------------------------------
示例
示例1
输入3
1,4
2,5

3,6
输出2
说明选取 2 条线段 [ 1,4 ] 和 [ 3,6 ],这两条线段可以覆盖 [ 2,5 ]。


解读与分析

题目解读

在一个一维坐标系中,有很多线段(通过起止点标识),在求出这些线段覆盖的范围之外,求这些线段中至少可以取几个就能覆盖这些范围。

分析与思路

在解答此题之前,先澄清一下,这些线段覆盖的范围可能是间断的区间。如 3 条线段 [1,4]、[2,5]、[6,7] 覆盖的区间是 [1,5]、[6,7]。

解答此题分三步:排序、分段、回溯。
1. 排序。对所有的线段排序。排序规则为,先对线段的起点进行排序,从小到大;如果起点相等,则对终点排序,也是从小到大。
2. 分段。在前文提到,这些线段覆盖的范围可能是间断的区间。所谓分段,就是找出这些间断的区间。
逐一遍历线段,如果后一个线段的起点大于前一个线段的终点,那么后一个线段就与前一个线段在不同的区间;否则,后一个线段一定与迁移线段处于同一个区间中。
所有位于不同区间的线段绝不会相交,因此,不同分段区间的线段可以单独统计,最后把所有区间的线段之和相加即可。
3. 回溯。对每个单独的区间,使用回溯算法,通过穷举得出所有可能覆盖的情况,从所有的情况中找出所需线段最小的情况。回溯可以使用递归实现,容易理解。

此题时间复杂度为 O(n^{2}),空间复杂度为 O(n)。


代码实现

Java代码

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;/*** 最少线段覆盖* * @since 2023.09.23* @version 0.1* @author Frank**/
public class MinLineCount {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {String input = sc.nextLine();int count = Integer.parseInt(input);List<int[]> lines = new ArrayList<>();for (int i = 0; i < count; i++) {input = sc.nextLine();String[] strStartEnd = input.split(",");int[] startEnd = new int[2];startEnd[0] = Integer.parseInt(strStartEnd[0]);startEnd[1] = Integer.parseInt(strStartEnd[1]);lines.add(startEnd);}processMinLineCount( lines);}}private static void processMinLineCount( List<int[]> lines) {// 1. 排序Comparator<int[]> cmp = new Comparator<int[]>() {@Overridepublic int compare(int[] o1, int[] o2) {for (int i = 0; i < o1.length; i++) {if (o1[i] != o2[i]) {return o1[i] - o2[i];}}return 0;}};lines.sort(cmp);// 2. 分段class LinePart {int start; // 起始点,包含在内int end; // 终止点,包含在内int startIdx; // 对应lines中的起始下标,包含在内int endIdx; // 对应lines中的终止下标,包含在内}List<LinePart> lpList = new ArrayList<LinePart>();LinePart tmpLP = new LinePart();for (int i = 0; i < lines.size(); i++) {int[] tmpLine = lines.get(i);if (i == 0) {tmpLP.start = tmpLine[0];tmpLP.end = tmpLine[1];tmpLP.startIdx = 0;tmpLP.endIdx = 0;lpList.add( tmpLP );continue;}// 不是同一个区间if( tmpLine[0] > tmpLP.end ){tmpLP = new LinePart();tmpLP.start = tmpLine[0];tmpLP.end = tmpLine[1];tmpLP.startIdx = i;tmpLP.endIdx = i;lpList.add( tmpLP );continue;}else  // 同一个区间{tmpLP.end = tmpLine[1];tmpLP.endIdx = i;}}//3.逐段求和int count = 0;for( int i = 0; i < lpList.size(); i ++ ){LinePart lpPart = lpList.get( i );List<int[]> tmpList = new ArrayList<int[]>();for( int j = lpPart.startIdx; j <= lpPart.endIdx; j ++ )	//  j <= lpPart.endIdx,包含在内{int[] tmpLine = lines.get( j );int[] copy = new int[2];copy[0] = tmpLine[0];copy[1] = tmpLine[1];tmpList.add( copy );}int partCount = getPartMinCount( tmpLP.start, tmpLP.end, tmpList );count += partCount;}System.out.println( count );}private static int getPartMinCount( int start, int end, List<int[]> list){if( start >= end ){return 0;}int minCount = list.size();for( int i = 0; i < list.size(); i ++ ){int tmpCount = 0;int[] cur = list.get( i );// 当它已经无法覆盖if( cur[0] > start ){break;}// 如果end小于start,那这样的线段根本不需要if( cur[1] < start  ){continue;}list.remove( i );tmpCount ++;tmpCount += getPartMinCount( cur[1], end, list);list.add( i, cur );if( tmpCount < minCount ){minCount = tmpCount;}}return minCount;}
}

JavaScript代码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {while (line = await readline()) {var count = parseInt(line);var lines = new Array();for (var i = 0; i < count; i++) {line = await readline();var strStartEnd = line.split(",");var startEnd = [];startEnd[0] = parseInt(strStartEnd[0]);startEnd[1] = parseInt(strStartEnd[1]);lines[i] = startEnd;}processMinLineCount(lines);}
}();function compareLineFun(a, b) {for (var i = 0; i < a.length; i++) {if (a[i] != b[i]) {return a[i] - b[i];}}return 0;
}function processMinLineCount(lines) {// 1. 排序lines.sort(compareLineFun);// 2. 分段// LinePart 的数据结构// LinePart  {//      start; // 起始点,包含在内//      end; // 终止点,包含在内//      startIdx; // 对应lines中的起始下标,包含在内//      endIdx; // 对应lines中的终止下标,包含在内//  }var lpList = new Array();var tmpLP = {};for (var i = 0; i < lines.length; i++) {var tmpLine = lines[i];if (i == 0) {tmpLP.start = tmpLine[0];tmpLP.end = tmpLine[1];tmpLP.startIdx = 0;tmpLP.endIdx = 0;lpList.push(tmpLP);continue;}// 不是同一个区间if (tmpLine[0] > tmpLP.end) {tmpLP = new LinePart();tmpLP.start = tmpLine[0];tmpLP.end = tmpLine[1];tmpLP.startIdx = i;tmpLP.endIdx = i;lpList.push(tmpLP);continue;} else // 同一个区间{tmpLP.end = tmpLine[1];tmpLP.endIdx = i;}}//3.逐段求和var count = 0;for (var i = 0; i < lpList.length; i++) {var lpPart = lpList[i];var tmpList = new Array();for (var j = lpPart.startIdx; j <= lpPart.endIdx; j++) //  j <= lpPart.endIdx,包含在内{var tmpLine = lines[j];var copy = [];copy[0] = tmpLine[0];copy[1] = tmpLine[1];tmpList.push(copy);}var partCount = getPartMinCount(tmpLP.start, tmpLP.end, tmpList);count += partCount;}console.log(count);
}function getPartMinCount(start, end, list) {if (start >= end) {return 0;}var minCount = list.length;for (var i = 0; i < list.length; i++) {var tmpCount = 0;var cur = list[i];// 当它已经无法覆盖if (cur[0] > start) {break;}// 如果end小于start,那这样的线段根本不需要if (cur[1] < start) {continue;}list.splice(i, 1);tmpCount++;tmpCount += getPartMinCount(cur[1], end, list);list.splice(i, 0, cur);if (tmpCount < minCount) {minCount = tmpCount;}}return minCount;
}

此题难度有些大,从思考算法,到实现代码并通过测试,都有不少工作量。在华为 OD 考题中,属于难度较大的题。

(完)

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

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

相关文章

【从0学习Solidity】36. 默克尔树 Merkle Tree

【从0学习Solidity】36. 默克尔树 Merkle Tree 博主简介&#xff1a;不写代码没饭吃&#xff0c;一名全栈领域的创作者&#xff0c;专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构&#xff0c;分享一些项目实战经验以及前沿技术的见解。关注我们的主页&#xf…

通俗易懂-OpenCV角点检测算法(Harris、Shi-Tomas算法实现)

目录 1 图像的特征 2&#xff0c;Harris角点检测 2.1 代码实现 2.2结果展示 3&#xff0c;Shi-Tomasi角点检测算法 3.1 &#xff0c; 代码实现 3.2结果展示 1 图像的特征 2&#xff0c;Harris角点检测 、 2.1 代码实现 import cv2 as cv import matplotlib.pyplot as …

QFrame类学习笔记

1、QFrame的作用 QFrame类继承于QWidget类&#xff0c;被QAbstractScrollArea, QLabel, QLCDNumber, QSplitter, QStackedWidget, and QToolBox等类继承。 QFrame作为许多基础控件的基类&#xff0c;提供许多成员方法给子类&#xff0c;实现子类的框架样式的设计。框架样式主要…

基于微信小程序的健身小助手打卡预约教学系统(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;用户的功能设计为&#xff1a;管理员的功能设计为&#xff1a;健身房的功能设计为&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获…

【数据结构】插入排序:直接插入排序、折半插入排序、希尔排序的学习知识总结

目录 1、排序的基本概念 2、直接插入排序 2.1 算法思想 2.2 代码实现 3、折半插入排序 3.1 算法思想 3.2 代码实现 4、希尔排序 4.1 算法思想 4..2 代码实现 1、排序的基本概念 排序是将一组数据按照预定的顺序排列的过程&#xff0c;排序的基本概念包括以下内容…

electron快速入门

新建electronstu01文件夹 以管理员身份运行powershell&#xff0c;切换到该文件下 npm init -y安装依赖包 npm install --save-dev electron失败 npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install --save-dev electron修改 package.json &qu…

正则表达式的应用(前端写法)

文章目录 1、匹配字符串中&#xff0c;a标签的href值2、校验邮箱3、校验手机号码3、待添加... 1、匹配字符串中&#xff0c;a标签的href值 (1) 代码 /*** description 匹配字符串中&#xff0c;a标签的href值* param {string} str 匹配的字符串* return {Array} 返回href值*/…

冒泡排序与选择排序(最low的两兄弟)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; 在我们的生活中&#xff0c;无处不在用到排序&#xff0c;比如说成绩的排名&#xff0c;淘宝&#xff0c;京东等等商品在各个方面的排序&#xff0c;这样看来一个好的算 法很重要&#xff0c;接下来我们要先…

JVM对象创建与内存分配机制

对象的创建 对象创建的主要流程: ​ 1.类加载检查 虚拟机遇到一条new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有&#xff0c;那必须先执行相应…

Lua学习笔记:debug.sethook函数

前言 本篇在讲什么 使用Lua的debug.setHook函数 本篇需要什么 对Lua语法有简单认知 依赖Sublime Text工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级标题 &…

【AI视野·今日NLP 自然语言处理论文速览 第三十八期】Thu, 21 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 21 Sep 2023 Totally 57 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Chain-of-Verification Reduces Hallucination in Large Language Models Authors Shehzaad Dhuliawala, Mojt…

华为杯数学建模比赛经验分享

再过一周左右,第二十届华为杯数学建模比赛就要开赛了&#xff0c;所以今天分享一下个人数学建模比赛的经验。 今天给大家分享一期关于华为杯数学建模比赛的经验分享&#xff0c;我将从以下三个方面展开说明&#xff1a; &#xff08;1&#xff09;如何准备数学建模比赛&#x…

系统集成|第十七章(笔记)

目录 第十七章 变更管理17.1 项目变更的基本概念17.2 变更管理的基本原则17.3 角色职位与工作程序17.4 相关事宜 上篇&#xff1a;第十六章、信息&#xff08;文档&#xff09;和配置管理 下篇&#xff1a;第十八章、安全管理 第十七章 变更管理 17.1 项目变更的基本概念 变更…

获取热门电影算法

功能#2&#xff1a;获取热门电影 为我们的“Netflix”项目实现“获取热门电影”功能。 我们将介绍以下内容 描述 解决方案 复杂性措施 时间复杂度 空间复杂度 描述# 现在&#xff0c;我们需要建立一个标准&#xff0c;以便将来自多个国家的顶级电影组合成一个单一的顶级电影…

24. 图论 - 图的表示种类

Hi,你好。我是茶桁。 之前的一节课中,我们了解了图的来由和构成,简单的理解了一下图的一些相关概念。那么这节课,我们要了解一下图的表示,种类。相应的,我们中间需要穿插一些新的知识点用于更好的去理解图,比如说邻接矩阵。 图的表示 我们一般用什么样的形式来表示图…

Linux su sudo命令

1、su命令——切换用户 1.1、切换到root用户(需要密码) su - root 1.2、切换到其他用户&#xff0c;比如jackma&#xff08;无需密码&#xff09; su - jackma 2、sudo命令——给普通用户添加root权限 2.1、用法 切换到root用户&#xff0c;执行visudo命令&#xff0c;会自动…

配置pytorchGPU虚拟环境-python3.7

cuda版本的pytorch包下载地址戳这里 winR->输入cmd->输nvcc -V回车 cuda 11.0 输入以下命令来查找 CUDA 的安装路径&#xff1a; Windows: where nvcc 输入以下命令来查找 cuDNN 的版本号&#xff1a; Windows: where cudnn* cuDNN 8.0 本机安装的是cuda 11.0&…

C语言数组和指针笔试题(三)(一定要看)

目录 字符数组四例题1例题2例题3例题4例题5例题6例题7 结果字符数组五例题1例题2例题3例题4例题5例题6例题7结果字符数组六例题1例题2例题3例题4例题5例题6例题7 结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412;个…

第二证券:迎政策助力,新型工业化爆发,德恩精工3日涨超60%

新式工业化概念26日盘中大幅拉升&#xff0c;到发稿&#xff0c;德恩精工、精伦电子、天永智能等涨停&#xff0c;固高科技涨约8%&#xff0c;亚威股份涨逾6%&#xff0c;金自天正、创世纪涨约5%。 值得注意的是&#xff0c;精伦电子已接连5个交易日涨停&#xff0c;公司昨日晚…

2023-09-21 buildroot linux 查看应用的log打印信息,命令cat /var/log/messages

一、应用会调用syslog 把打印信息输出到串口&#xff0c;debug 串口会打印kernel的log和上层应用的的log。 二、linux 命令cat /var/log/messages查看应用log