华为OD机试真题—— 最少数量线段覆盖/多线段数据压缩(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

news2025/6/3 20:35:25

在这里插入图片描述

2025 A卷 100分 题型

本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析;
并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式!

2025华为OD真题目录+全流程解析/备考攻略/经验分享

华为OD机试真题《最少数量线段覆盖/多线段数据压缩》:


目录

    • 题目名称:最少数量线段覆盖/多线段数据压缩
      • 题目描述
    • Java
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 测试示例
      • 综合分析
    • python
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 测试示例
      • 综合分析
    • JavaScript
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 测试示例
      • 综合分析
    • C++
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 测试示例
      • 综合分析
    • C语言
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 测试示例
      • 综合分析
    • GO
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 测试示例
      • 综合分析


题目名称:最少数量线段覆盖/多线段数据压缩


知识点:排序、贪心算法
时间限制:1秒
空间限制:256MB
限定语言:不限


题目描述

给定坐标轴上的一组线段(起点和终点为整数且长度≥1),从中选出最少数量的线段,使其能覆盖所有线段。

输入描述:

  • 第一行为线段数量N(≤10000)
  • 后续N行每行为线段起点和终点,格式为"x,y"(取值范围[-10⁵, 10⁵])

输出描述:

  • 最少线段数量(正整数)

示例:
输入:

3  
1,4  
2,5  
3,6  

输出:

2  

说明:选取线段[1,4]和[3,6],可覆盖所有线段。


Java

问题分析

我们需要从一组线段中选出最少数量的线段,使得它们的并集覆盖所有原始线段的并集。例如,输入三个线段 [1,4][2,5][3,6],它们的并集是 [1,6],选择 [1,4][3,6] 即可覆盖整个区间。


解题思路

  1. 排序线段:将所有线段按起点从小到大排序,若起点相同则按终点从大到小排序。
  2. 贪心算法:每次选择能覆盖当前最左端点且右端点最远的线段,逐步扩展覆盖范围。
  3. 终止条件:当覆盖范围达到所有线段的最大右端点时结束。

代码实现

import java.util.*;

class Segment {
   
    int start;
    int end;

    public Segment(int start, int end) {
   
        this.start = start;
        this.end = end;
    }
}

public class Main {
   
    public static void main(String[] args) {
   
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.nextLine(); // 读取换行符

        List<Segment> segments = new ArrayList<>();

        // 1. 读取所有线段
        for (int i = 0; i < n; i++) {
   
            String[] parts = scanner.nextLine().split(",");
            int start = Integer.parseInt(parts[0]);
            int end = Integer.parseInt(parts[1]);
            segments.add(new Segment(start, end));
        }

        // 2. 排序线段:按起点升序,若起点相同按终点降序
        segments.sort((a, b) -> {
   
            if (a.start != b.start) {
   
                return Integer.compare(a.start, b.start);
            } else {
   
                return Integer.compare(b.end, a.end);
            }
        });

        // 3. 找到所有线段的合并区间的总范围
        int L = Integer.MAX_VALUE;
        int R = Integer.MIN_VALUE;
        for (Segment seg : segments) {
   
            if (seg.start < L) L = seg.start;
            if (seg.end > R) R = seg.end;
        }

        int count = 0; // 记录选择的线段数量
        int currentEnd = L; // 当前覆盖的最右端点
        int i = 0; // 遍历线段的指针

        // 4. 贪心算法:每次选择能覆盖当前最左端点且最远的线段
        while (currentEnd < R) {
   
            int maxEnd = currentEnd; // 当前能覆盖的最远右端点
            boolean found = false; // 是否找到可扩展的线段

            // 遍历所有起点小于等于 currentEnd 的线段
            while (i < segments.size() && segments.get(i).start <= currentEnd) {
   
                if (segments.get(i).end > maxEnd) {
   
                    maxEnd = segments.get(i).end;
                    found = true; // 找到可扩展的线段
                }
                i++; // 移动指针
            }

            if (!found) {
    // 无解,无法覆盖整个区间
                System.out.println(-1);
                return;
            }

            count++; // 选中线段
            currentEnd = maxEnd; // 更新当前覆盖的最右端点
        }

        System.out.println(count);
    }
}

代码详细解析

  1. 读取输入

    • 读取线段数量 n,然后逐行读取每个线段的起点和终点,存入 List<Segment>
  2. 排序线段

    • 按起点从小到大排序,若起点相同则按终点从大到小排序。这确保在相同起点的线段中优先选择更长的线段。
  3. 确定总区间范围

    • 遍历所有线段,找到最小的起点 L 和最大的终点 R,即所有线段合并后的总区间。
  4. 贪心算法核心

    • currentEnd 表示当前覆盖的最右端点,初始化为 L
    • 在每次循环中,找到所有起点小于等于 currentEnd 的线段中右端点最大的线段。
    • 若找不到能扩展覆盖范围的线段,则输出 -1
    • 每选择一个线段,更新 currentEnd 并增加计数器 count

测试示例

示例1:

输入:
3
1,4
2,5
3,6

输出:
2

解析:排序后线段顺序为 [1,4], [2,5], [3,6]。第一次选择 [1,4],覆盖到4;第二次选择 [3,6],覆盖到6,总数量为2。

示例2:

输入:
2
1,3
4,6

输出:
-1

解析:线段 [1,3][4,6] 无法覆盖中间区间 [3,4],返回 -1


综合分析

  1. 时间复杂度

    • 排序时间复杂度为 O(n log n)
    • 贪心算法遍历线段时间复杂度为 O(n)
    • 总体时间复杂度为 O(n log n),适用于 n ≤ 10000
  2. 空间复杂度

    • 存储线段需要 O(n) 空间。
  3. 优势

    • 贪心算法保证每次选择最优线段,确保全局最优。
    • 排序策略简化了后续选择过程。
  4. 适用性

    • 适用于需要覆盖连续区间且线段可能重叠的场景。

python

问题分析

我们需要从一组线段中选出最少数量的线段,使得它们的并集覆盖所有原始线段的并集。例如,输入三个线段 [1,4][2,5][3,6],它们的并集是 [1,6],选择 [1,4][3,6] 即可覆盖整个区间。


解题思路

  1. 排序线段:将线段按起点升序排序,若起点相同则按终点降序排序。
  2. 贪心算法:每次选择能覆盖当前最左端点且右端点最远的线段,逐步扩展覆盖范围。
  3. 终止条件:当覆盖范围达到所有线段的最大右端点时结束。

代码实现

class Segment:
    def __init__(self, start, end):
        self.start = start
        self.end = end

n = int(input())
segments = []
for _ in range(n):
    x, y = map(int, input().split(','))
    segments.append(Segment(x, y))

# 1. 按起点升序排序,起点相同则按终点降序排序
segments.sort(key=lambda s: (s.start, -s.end))

# 2. 计算总区间的起点L和终点R
if not segments:
    print(0)
    exit()
L = min(s.start for s in segments)
R = max(s.end for s in segments)

count = 0
current_end = L  # 当前覆盖的最右端点
i = 0  # 遍历线段的指针

# 3. 贪心算法:每次选择能覆盖当前最左端点且最远的线段
while current_end < R:
    max_end = -float('inf')
    # 遍历所有起点 <= current_end 的线段,找到最大终点
    while i < len(segments) and segments[i].start <= current_end:
        if segments[i].end > max_end:
            max_end = segments[i].end
        i += 1
    if max_end == -float('inf'):  # 无法覆盖整个区间
        print(-1)
        exit

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

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

相关文章

C语言创意编程:用趣味实例玩转基础语法(2)

文章目录 0. 前言1. &#x1f4ca; 动态条形图1.1 程序效果展示1.2 完整代码解析1.3 关键技术详解1.3.1 Unicode字符应用1.3.2 函数封装思想1.3.3 输入处理1.3.4 跨平台考虑 2. &#x1f524; 字母金字塔2.1 程序效果展示2.2 完整代码解析2.3 关键技术详解2.3.1 嵌套循环结构2.…

OpenCV CUDA模块图像处理------颜色空间处理之GPU 上对两张带有 Alpha 通道的图像进行合成操作函数alphaComp()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于在 GPU 上对两张带有 Alpha 通道的图像进行合成操作。支持多种常见的 Alpha 合成模式&#xff08;Porter-Duff 合成规则&#xff09;&…

OpenWebUI(1)源码学习构建

1. 前言 通过docker镜像拉取安装就不介绍了&#xff0c;官方的命令很多。本节主要撸一撸源码&#xff0c;所以&#xff0c;本地构建 2. 技术框架和启动环境 后端python&#xff0c;前端svelte 环境要求&#xff1a;python > 3.11 &#xff0c;Node.js > 20.10 3. 源…

npm error Cannot find module ‘negotiator‘ 的处理

本想运行npm create vuelatest&#xff0c;但提示&#xff1a; npm error code MODULE_NOT_FOUND npm error Cannot find module negotiator npm error Require stack: npm error - C:\Users\Administrator\AppData\Roaming\nvm\v18.16.1\node_modules\npm\node_modules\tuf-j…

爬虫入门指南-某专利网站的专利数据查询并存储

免责声明 本教程仅用于教育目的&#xff0c;演示如何合法获取公开专利数据。在实际操作前&#xff0c;请务必&#xff1a; 1. 仔细阅读目标网站的robots.txt文件和服务条款 2. 控制请求频率&#xff0c;避免对服务器造成负担 3. 仅获取和使用公开数据 4. 不用于商业用途或…

SQL(Database Modifications)

目录 Insertion Specifying Attributes in INSERT Adding Default Values&#xff08;缺省值&#xff09; Inserting Many Tuples Creating a Table Using the SELECT INTO Statement Deletion Example: Deletion Semantics of Deletion Updates Example: Update Sev…

【android bluetooth 案例分析 04】【Carplay 详解 2】【Carplay 连接之手机主动连车机】

1. 背景 在【android bluetooth 案例分析 04】【Carplay 详解 1】【CarPlay 在车机侧的蓝牙通信原理与角色划分详解】中我们从整理上介绍了车机中 carplay 相关基础概念。 本节 将详细分析 iphone手机主动 连接 车机carplay 这一过程。 先回顾一下 上一节&#xff0c; carpla…

【仿muduo库实现并发服务器】实现时间轮定时器

实现时间轮定时器 1.时间轮定时器原理2.项目中实现目的3.实现功能3.1构造定时任务类3.2构造时间轮定时器每秒钟往后移动添加定时任务刷新定时任务取消定时任务 4.完整代码 1.时间轮定时器原理 时间轮定时器的原理类似于时钟&#xff0c;比如现在12点&#xff0c;定一个3点的闹…

day15 leetcode-hot100-28(链表7)

2. 两数相加 - 力扣&#xff08;LeetCode&#xff09; 1.模拟 思路 最核心的一点就是将两个链表模拟为等长&#xff0c;不足的假设为0&#xff1b; &#xff08;1&#xff09;设置一个新链表newl来代表相加结果。 &#xff08;2&#xff09;链表1与链表2相加&#xff0c;具…

​​知识图谱:重构认知的智能革命​

在数字经济的浪潮中&#xff0c;知识图谱正悄然掀起一场认知革命。它不仅是技术的迭代&#xff0c;更是人类从“数据依赖”迈向“知识驱动”的里程碑。当谷歌用知识图谱优化搜索引擎、银行用它穿透复杂的金融欺诈网络、医院用它辅助癌症诊疗时&#xff0c;这项技术已悄然渗透到…

【计算机网络】4网络层①

这篇笔记讲IPv4和IPv6。 为了解决“IP地址耗尽”问题,有三种措施: ①CIDR(延长IPv4使用寿命) ②NAT(延长IPv4使用寿命) ③IPv6(从根本上解决IP地址耗尽问题) IPv6 在考研中考查频率较低,但需掌握基础概念以防冷门考点,重点结合数据报格式和与 IPv4 的对比记忆。…

MATLAB中的table数据类型:高效数据管理的利器

MATLAB中的table数据类型&#xff1a;高效数据管理的利器 什么是table数据类型&#xff1f; MATLAB中的table是一种用于存储列向数据的数据类型&#xff0c;它将不同类型的数据组织在一个表格结构中&#xff0c;类似于电子表格或数据库表。自R2013b版本引入以来&#xff0c;t…

Dropout 在大语言模型中的应用:以 GPT 和 BERT 为例

引言 大型语言模型&#xff08;LLMs&#xff09;如 GPT&#xff08;生成式预训练 Transformer&#xff09;和 BERT&#xff08;双向编码器表示 Transformer&#xff09;通过其强大的语言理解和生成能力&#xff0c;彻底改变了自然语言处理&#xff08;NLP&#xff09;领域。然…

gitLab 切换中文模式

点击【头像】--选择settings 选择【language】,选择中文&#xff0c;点击【保存】即可。

133.在 Vue3 中使用 OpenLayers 实现画多边形、任意编辑、遮罩与剪切处理功能

&#x1f3ac; 效果演示截图&#xff08;先睹为快&#xff09; ✨ 功能概览&#xff1a; ✅ 鼠标画任意形状多边形&#xff1b; ✏️ 点击“修改边界”可拖动顶点&#xff1b; &#x1f7e5; 点击“遮罩”后地图除多边形区域外变红&#xff1b; ✂️ 点击“剪切”后仅显示选…

4.8.4 利用Spark SQL实现分组排行榜

在本次实战中&#xff0c;我们的目标是利用Spark SQL实现分组排行榜&#xff0c;特别是计算每个学生分数最高的前3个成绩。任务的原始数据由一组学生成绩组成&#xff0c;每个学生可能有多个成绩记录。我们首先将这些数据读入Spark DataFrame&#xff0c;然后按学生姓名分组&am…

【五子棋在线对战】一.前置知识的了解

前置知识的了解 前言1.Websocketpp1.1 使用Websocketpp的原因1.2 Websocket常用接口1.3 Websocket搭建服务器流程 2.JsonCpp2.1 Json 数据对象类的表示2.2序列化和反序列化的接口2.3 演示代码 3.Mysql![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/93305f423b544fc1…

历年中国科学技术大学计算机保研上机真题

2025中国科学技术大学计算机保研上机真题 2024中国科学技术大学计算机保研上机真题 2023中国科学技术大学计算机保研上机真题 在线测评链接&#xff1a;https://pgcode.cn/school?classification1 拆分数字 题目描述 给定一个数字&#xff0c;拆分成若干个数字之和&#xff…

HackMyVM-Art

信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-31 03:00 EDT Nmap scan report for 192.168.43.1 Host is up (0.0047s latency). MAC Address: C6:45:66:05:91:88 (Unknown) Nmap scan rep…

网页前端开发(基础进阶1)

颜色表示方法3种&#xff1a; 1.关键字&#xff1a; color&#xff1a;green&#xff1b; gray red yellow 2.rgb表示法&#xff1a;红&#xff0c;绿&#xff0c;蓝三原色。rgb&#xff08;r&#xff0c;g&#xff0c;b&#xff09;&#xff0c;r表示红色&#xff0c;g表示绿…