全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:最少数量线段覆盖
知识点排序贪心
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
给定坐标轴上的一组线段,线段的起点和终点均为整数并且长度不小于1,请你从中找到最少数量的线段,这些线段可以覆盖住所有线段。
输入描述:
第一行输入为所有线段的数量,不超过10000,后面每行表示一条线段,格式为”x,y”,x和y分别表示起点和终点,取值范围是[-105,105]。
输出描述:
最少线段数量,为正整数
示例1
输入:
3
1,4
2,5
3,6
输出:
2
说明:
选取2条线段[1,4]和[3,6]即可,这两条线段可以覆盖[2,5]
解题思路:
例如:
3
1,4
3,6
5,8
首先对上面的线段进行排序,排序的规则:
按照线段左节点升序排序
左节点相等的,按右节点降序排序
根据线段1,初始化right=4,maxRight=4,res=1;
线段2的左节点小于right,表示后面允许有某个线段与线段1来覆盖线段2;更新maxRight=6
线段3的左节点大于right,表示后面不可能有某个线段与right之前的线段来覆盖线段3(因为线段已经排过序了):
因为maxRight>right,证明maxRight与right之间有线段没有被覆盖,所以res+1=2,right也更新为maxRight=6;
因为线段3的左节点小于maxRight,说明在maxRight之前有线段与线段3有交集,证明后面有覆盖的可能;更新maxRight=8;
最后因为maxRight=8>right=6;证明线段没有覆盖,res+1=3;
最终结果为3
代码实现:Java代码满分实现
package com.codernav.demo.hwod.exam; import java.util.Arrays; import java.util.Scanner; /** * @title 最少数量线段覆盖 * @Description 给定坐标轴上的一组线段,线段的起点和终点均为整数并且长度不小于1,请你从中找到最少数量的线段,这些线段可以覆盖住所有线段。 * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/28 */ public class Main { public static void main(String[] args) { Node[] arr = new Node[10000]; Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for (int i = 0; i < n; i++) { String[] s = sc.next().split(","); int v1 = Integer.parseInt(s[0]); int v2 = Integer.parseInt(s[1]); arr[i] = new Node(v1, v2); } Arrays.sort(arr, 0, n - 1); if (n == 0) { System.out.println(0); } else { int res = 1; //覆盖线段分界点(左侧已经被覆盖) int right = arr[0].r; //最大的右侧节点 int maxRight = arr[0].r; for (int i = 1; i < n; i++) { if (arr[i].l > right) { //说明right左侧的线段与线段arr[i]没有交集(无法进行覆盖了) if (maxRight > right) { //说明right到maxRight之间有线段之前没有覆盖,现在需要新的线段覆盖 res++; //更新分界点为maxRight right = maxRight; } if (maxRight < arr[i].l) { //说明arr[i]跟前面所有的线段都没有交集,重新开始计算了 res++; //分界点也要变成arr[i]的右节点(相当于初始化了) right = arr[i].r; } } //线段最右节点需要更新 maxRight = Math.max(arr[i].r, maxRight); } if (maxRight > right) { //说明right到maxRight之间有线段还没有覆盖,需要再加一条 res++; } System.out.println(res); } } static class Node implements Comparable<Node> { int l, r; public Node(int l, int r) { this.l = l; this.r = r; } @Override public int compareTo(Node o) { if (l == o.l) { return o.r - r; } return l - o.l; } } }