华为OD机试 - 区间交叠问题 - 贪心算法(Python/JS/C/C++ 2024 E卷 100分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

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

二、输入描述

第一行输入为所有线段的数量,不超过10000,后面每行表示一条线段,格式为"x,y",x和y分别表示起点和终点。

三、输出描述

最少线段数量,为正整数。

四、测试用例

测试用例1:

1、输入

3
1,4
2,5
3,6

2、输出

2

3、说明

选择线段 [1,4] 和 [3,6],即可覆盖所有线段。

测试用例2:

1、输入

4
1,10
2,3
4,5
6,7

2、输出

1

3、说明

选择线段 [1,10],即可覆盖所有线段。

五、解题思路

1、贪心算法

贪心算法适用于此类优化问题,通过每次做出局部最优的选择,最终达到全局最优。它在此问题中能够有效地选择最少数量的线段来覆盖所有给定的线段的并集。

排序是贪心算法的前置步骤,通过特定的排序规则(起点升序,终点降序),可以确保在选择线段时,覆盖范围更大的线段优先被选中,从而减少总的选择次数。

数组或列表作为基础的数据结构,方便存储和管理大量的线段,并且能够高效地进行遍历和排序操作。

2、具体步骤

  1. 将所有线段按照起点升序排序。如果起点相同,则按照终点降序排序。这有助于在选择线段时,优先考虑起点靠前且覆盖范围更大的线段。
  2. 初始化一个变量 currentEnd,用于记录当前已覆盖的最右端点,初始值设为负无穷。
  3. 初始化一个变量 count,记录选择的线段数量,初始值为0。
  4. 遍历排序后的线段列表,对于每一条线段:
    • 如果当前线段的起点大于 currentEnd,说明现有的覆盖范围无法覆盖这条线段,需要选择一条新的线段来扩展覆盖范围。选择当前线段,并将 currentEnd 更新为该线段的终点,同时将 count 加1。
    • 否则,更新 currentEnd 为当前线段终点与 currentEnd 中的较大值,以扩展覆盖范围。
  5. 最终选择的线段数量 count 即为覆盖所有线段所需的最少线段数量。

3、时间复杂度分析

排序步骤的时间复杂度为 O(nlogn),其中 n 为线段数量。

遍历和选择线段的步骤时间复杂度为 O(n)。

因此,总体时间复杂度为 O(nlogn),适用于线段数量较大的情况(如本题中的 10000 条线段)。

六、Python算法源码

# 导入必要的模块
import sysdef minimal_cover_segments():# 读取所有输入行lines = sys.stdin.read().strip().split('\n')n = int(lines[0])  # 读取线段数量segments = []# 读取每条线段的起点和终点for i in range(1, n+1):x, y = map(int, lines[i].split(','))if x > y:x, y = y, x  # 确保起点小于等于终点segments.append((x, y))# 按起点升序排序,若起点相同,则按终点降序排序segments.sort(key=lambda s: (s[0], -s[1]))count = 0  # 记录需要的线段数量current_end = -float('inf')  # 当前覆盖的最右端点next_end = -float('inf')  # 在当前覆盖范围内能达到的最远端点i = 0  # 当前遍历到的线段索引while i < n:# 如果当前线段的起点大于当前覆盖范围,需要选择新的线段if segments[i][0] > current_end:# 更新覆盖范围为在当前范围内能达到的最远端点current_end = next_endcount += 1# 如果当前线段的起点仍大于新的覆盖范围,说明无法覆盖if segments[i][0] > current_end:current_end = segments[i][1]count +=1else:# 更新能达到的最远端点next_end = max(next_end, segments[i][1])i +=1# 最后一次更新覆盖范围if next_end > current_end:count +=1# 输出最少线段数量print(count)# 调用主函数
if __name__ == "__main__":minimal_cover_segments()

七、JavaScript算法源码

// 定义主函数
function minimalCoverSegments() {const fs = require('fs');// 读取标准输入const input = fs.readFileSync('/dev/stdin', 'utf8').trim().split('\n');const n = parseInt(input[0]); // 读取线段数量let segments = [];// 读取每条线段的起点和终点for (let i = 1; i <= n; i++) {let [x, y] = input[i].split(',').map(Number);if (x > y) {[x, y] = [y, x]; // 确保起点小于等于终点}segments.push([x, y]);}// 按起点升序排序,若起点相同,则按终点降序排序segments.sort((a, b) => {if (a[0] !== b[0]) {return a[0] - b[0];} else {return b[1] - a[1];}});let count = 0; // 记录需要的线段数量let currentEnd = -Infinity; // 当前覆盖的最右端点let nextEnd = -Infinity; // 在当前覆盖范围内能达到的最远端点let i = 0; // 当前遍历到的线段索引while (i < n) {// 如果当前线段的起点大于当前覆盖范围,需要选择新的线段if (segments[i][0] > currentEnd) {// 更新覆盖范围为在当前范围内能达到的最远端点currentEnd = nextEnd;count++;// 如果当前线段的起点仍大于新的覆盖范围,说明无法覆盖if (segments[i][0] > currentEnd) {currentEnd = segments[i][1];count++;}} else {// 更新能达到的最远端点nextEnd = Math.max(nextEnd, segments[i][1]);}i++;}// 最后一次更新覆盖范围if (nextEnd > currentEnd) {count++;}// 输出最少线段数量console.log(count);
}// 调用主函数
minimalCoverSegments();

八、C算法源码

#include <stdio.h>
#include <stdlib.h>// 定义线段结构体
typedef struct {int start;int end;
} Segment;// 比较函数,用于qsort,按起点升序,若起点相同则按终点降序
int compare(const void* a, const void* b) {Segment* s1 = (Segment*)a;Segment* s2 = (Segment*)b;if (s1->start != s2->start) {return s1->start - s2->start;} else {return s2->end - s1->end;}
}int main(){int n;scanf("%d", &n); // 读取线段数量Segment segments[n];// 读取每条线段的起点和终点for(int i=0; i<n; i++) {scanf("%d,%d", &segments[i].start, &segments[i].end);if (segments[i].start > segments[i].end) {// 确保起点小于等于终点int temp = segments[i].start;segments[i].start = segments[i].end;segments[i].end = temp;}}// 按起点升序排序,若起点相同则按终点降序排序qsort(segments, n, sizeof(Segment), compare);int count = 0; // 记录需要的线段数量int currentEnd = -2147483648; // 当前覆盖的最右端点int nextEnd = -2147483648; // 在当前覆盖范围内能达到的最远端点int i =0; // 当前遍历到的线段索引while(i < n){if (segments[i].start > currentEnd){// 更新覆盖范围为在当前范围内能达到的最远端点currentEnd = nextEnd;count++;// 如果当前线段的起点仍大于新的覆盖范围,说明无法覆盖if (segments[i].start > currentEnd){currentEnd = segments[i].end;count++;}} else {// 更新能达到的最远端点if (segments[i].end > nextEnd){nextEnd = segments[i].end;}}i++;}// 最后一次更新覆盖范围if (nextEnd > currentEnd){count++;}// 输出最少线段数量printf("%d\n", count);return 0;
}

九、C++算法源码

#include <bits/stdc++.h>
using namespace std;// 定义线段结构体
struct Segment {int start;int end;
};// 比较函数,用于排序,按起点升序,若起点相同则按终点降序
bool compareSegments(const Segment& a, const Segment& b){if(a.start != b.start){return a.start < b.start;}return a.end > b.end;
}int main(){ios::sync_with_stdio(false);cin.tie(0);int n;cin >> n; // 读取线段数量vector<Segment> segments(n);// 读取每条线段的起点和终点for(int i=0; i<n; i++){char comma;cin >> segments[i].start >> comma >> segments[i].end;if(segments[i].start > segments[i].end){// 确保起点小于等于终点swap(segments[i].start, segments[i].end);}}// 按起点升序排序,若起点相同则按终点降序排序sort(segments.begin(), segments.end(), compareSegments);int count = 0; // 记录需要的线段数量int currentEnd = INT32_MIN; // 当前覆盖的最右端点int nextEnd = INT32_MIN; // 在当前覆盖范围内能达到的最远端点int i =0; // 当前遍历到的线段索引while(i < n){if(segments[i].start > currentEnd){// 更新覆盖范围为在当前范围内能达到的最远端点currentEnd = nextEnd;count++;// 如果当前线段的起点仍大于新的覆盖范围,说明无法覆盖if(segments[i].start > currentEnd){currentEnd = segments[i].end;count++;}} else {// 更新能达到的最远端点if(segments[i].end > nextEnd){nextEnd = segments[i].end;}}i++;}// 最后一次更新覆盖范围if(nextEnd > currentEnd){count++;}// 输出最少线段数量cout << count << "\n";return 0;
}

🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

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

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

相关文章

Django的请求与响应

Django的请求与响应 1、常见的请求2、常见的响应3、案例 1、常见的请求 函数的参数request是一个对象&#xff0c;封装了用户发送过来的所有请求相关数据。 get请求一般用来请求获取数据&#xff0c;get请求也可以传参到后台&#xff0c;但是传递的参数显示在地址栏。 post请求…

【CSS3】css开篇基础(2)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

el-date-picker设置只有某些日期可选

示例图&#xff1a; <el-date-pickerv-model"topFormObj.upTime"type"date"value-format"timestamp"format"dd/MM/yyyy":picker-options"pickerOptions" /> 固定限制每周的周末周三不可选 data() {return {pickerOp…

[Python学习日记-46] Python 中第三方开源模块的安装、使用与上传自己写的模块

[Python学习日记-46] Python 中第三方开源模块的安装、使用与上传自己写的模块 简介 下载与安装 如何使用安装好的第三方开源模块 如何上传自己写的模块到 PyPi 简介 在前面的模块介绍和导入当中主要介绍的都是 Python 内置的一些模块&#xff0c;我们把它称为标准库&#…

【多版本并发控制(MVCC)】

并发事务问题&#xff1a; MySQL隔离级别-未提交读&#xff0c;提交读&#xff0c;可重复读&#xff0c;序列化 隔离级别对于并发事务的解决情况 隔离级别脏读不可重复读幻读未提交读不可不可不可读已提交可不可不可可重复读 &#xff08;默认&#xff09;可可不可串行化&…

vue+echarts实现雷达图及刻度标注

文章目录 前言代码实现实现效果总结 前言 最近项目有做数据可视化 大屏 不免再次使用些echarts应用 记录下其中echarts雷达图的实现 代码实现 先上代码 <template><div class"container"><div ref"chart" style"width: 500px; heig…

树莓派应用--AI项目实战篇来啦-11.OpenCV定位物体的实时位置

1. 介绍 本项目通过PCA9685舵机控制模块控制二自由度舵机云台固定在零点位置&#xff0c;然后通OpenCV检测到黄色小熊&#xff0c;找到中心位置并打印出中心位置的坐标&#xff0c;通过双色LED灯进行指示是否检测到目标&#xff0c;本项目为后面二维云台追踪物体和追踪人脸提供…

grpc的python使用

RPC 什么是 RPC &#xff1f; RPC&#xff08;Remote Procedure Call&#xff09;远程过程调用&#xff0c;是一种计算机通信协议&#xff0c;允许一个程序&#xff08;客户端&#xff09;通过网络向另一个程序&#xff08;服务器&#xff09;请求服务&#xff0c;而无需了解…

Cef加载自定义本地资源

在Cef auto build下载cefCEF Automated Builds 我下载的是104&#xff0c;使用cefsimple工程。 例如&#xff1a;前端资源如下 通过http协议把前端资源加载出来。所有的资源都通过http://local.test.cn/xxx加载。 前端资源包括index.html、test.css、test.js index.html&am…

福州少儿自闭症寄宿制学校:专注关爱每个孩子

在福州&#xff0c;少儿自闭症寄宿制学校以其专注与关爱&#xff0c;为自闭症儿童提供了一个温暖的避风港。这些学校不仅提供教育服务&#xff0c;更是一个充满爱与包容的大家庭&#xff0c;让孩子们在这里找到归属感和自信心。然而&#xff0c;当我们把目光投向广州&#xff0…

《鸟哥的Linux私房菜基础篇》---1 Linux的介绍与如何开启Linux之路

目录 一、Linux的简单介绍 1、Linux的简介 2、Linux的起源与发展 3、主要特点 4、应用场景 二、开启Linux之路 1、学习Linux的相关知识 2、正规表示法、管线命令、数据流重导向 前言 整体大纲预览 一、Linux的简单介绍 1、Linux的简介 &#xff08;1&#xff09;Linu…

[棋牌源码] 2023情怀棋牌全套源代码含多套大厅UI及600+子游源码下载

降维打击带来的优势 这种架构不仅极大提升了运营效率&#xff0c;还降低了多端维护的复杂性和成本。运营商无需投入大量资源维护多套代码&#xff0c;即可实现产品的全终端覆盖和快速更新&#xff0c;这就是产品层面的降维打击。 丰富的游戏内容与多样化大厅风格 类型&#…

VS2017 编译 SQLite3 动态库

首先官方下载源码: Tags sqlite/sqlite (github.com) 1.安装 VS2017 community edition 2.打开VS2017命令行工具 3.安装TCL 开发库,推荐 TCL 9.0 先下载源码: Tcl/Tk 9.0 使用vs2017编译tcl&

图书馆自习室座位预约管理微信小程序+ssm(lw+演示+源码+运行)

摘 要 随着电子商务快速发展世界各地区,各个高校对图书馆也起来越重视.图书馆代表着一间学校或者地区的文化标志&#xff0c;因为图书馆丰富的图书资源能够带给我们重要的信息资源&#xff0c;图书馆管理系统是学校管理机制重要的一环&#xff0c;,面对这一世界性的新动向和新…

vue3中监视 Reactive对象中的属性

watch 的第一个参数可以是不同形式的“数据源”&#xff1a;它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组 一、框架&#xff1a; <template><div class"divBox"><h2>姓名&#xff1a;{{ person.…

ElasticSearch是什么?

1.概述 Elasticsearch 是一个基于 Apache Lucene 构建的开源分布式搜索引擎和分析引擎。它专为云计算环境设计&#xff0c;提供了一个分布式的、高可用的实时分析和搜索平台。Elasticsearch 可以处理大量数据&#xff0c;并且具备横向扩展能力&#xff0c;能够通过增加更多的硬…

力扣周赛:第419场周赛

&#x1f468;‍&#x1f393;作者简介&#xff1a;爱好技术和算法的研究生 &#x1f30c;上期文章&#xff1a;力扣周赛&#xff1a;第415场周赛 &#x1f4da;订阅专栏&#xff1a;力扣周赛 希望文章对你们有所帮助 因为一些特殊原因&#xff0c;这场比赛就打了1h&#xff0c…

Linux——传输层协议

目录 一再谈端口号 1端口号范围划分 2两个问题 3理解进程与端口号的关系 二UDP协议 1格式 2特点 3进一步理解 3.1关于UDP报头 3.2关于报文 4基于UDP的应用层协议 三TCP协议 1格式 2TCP基本通信 2.1关于可靠性 2.2TCP通信模式 3超时重传 4连接管理 4.1建立…

【uni-app】HBuilderX安装uni-ui组件

目录 1、官网找到入口 2、登录帐号 3、打开HuilderX 4、选择要应用的项目 5、查看是否安装完成 6、按需安装 7、安装完毕要重启 8、应用 前言&#xff1a;uniapp项目使用uni-ui组件方式很多&#xff0c;有npm安装等&#xff0c;或直接创建uni-ui项目&#xff0c;使用un…

开源商城系统crmeb phpstudy安装配置

BOSS让我最快时间部署一套开源商场系统&#xff0c;今天就以crmeb为例。 快速部署在linux中我会首选docker&#xff0c;因为我要在windows中部署&#xff0c;本文就选用phpstudy集成环境做了。 什么是crmeb 我从官网摘点&#xff1a; CRMEB产品与服务 CRMEB通过将CRM&#x…