华为OD题目:最少数量线段覆盖

华为OD题目:最少数量线段覆盖

知识点排序贪心Q
时间限制: 1s 空间限制: 256MB 限定语言: 不限
题目描述:
给定坐标轴上的一组线段,线段的起点和终点均为整数并且长度不小于1,请你从中找到最少数量的线段,这些线段可以覆盖住所有线段。

输入描述:第一行输入为所有线段的数量,不超过10000,后面每行表示一条线段,格式为”x,y",x和y分别表示起点和终点,取值范围是[-105,1051]
输出描述:
最少线段数量,为正整数

示例1
输入:
3
1,4
2,5
3,6
输出:
2

4
1,4
2,5
3,6
10,20
输出:
3

4
1,4
2,5
3,6
1,10
输出:
3

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

解题思路:

  • 参考: https://blog.csdn.net/qq_34465338/article/details/128478461
    在这里插入图片描述
public class My {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = Integer.parseInt(sc.nextLine());


        List<int[]> list = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            String line = sc.nextLine();
            String[] strings = line.split(",");
            int left = Integer.parseInt(strings[0]);
            int right = Integer.parseInt(strings[1]);
            int[] node = new int[]{left, right};
            list.add(node);
        }
        //将每个线段,按照左侧升序排列,如果左侧相等,则按照右侧降序排列(这里千万不要搞错了)
        list.sort((a1, a2) -> {
            if (a1[0] != a2[0]) {
                return a1[0] - a2[0];
            }else {
                return a2[1] - a1[1];
            }
        });

        //下面是初始化
        int total = 1;
        int[] ints = list.get(0);
        //已经覆盖的右节点
        int coveredRight = ints[1];
        //最大右节点
        int maxRight = ints[1];

        for (int i = 1; i < list.size(); i++) {
            int[] node = list.get(i);
            int left = node[0];
            int right = node[1];
            //如果当前线段左节点比前面的右节点小,说明此线段可以和前面的合并,
            if (left <= coveredRight) {
                //如果此线段的右节点比maxRight大,更新maxRight
                maxRight = Math.max(maxRight, right);
            }else {
                //如果当前线段左节点比前面的右节点大,先将之前未合并的合并,合并次数+1,合并后 覆盖线段右节点coveredRight 设置为maxRight
                if (maxRight > coveredRight) {
                    total++;
                    coveredRight = maxRight;
                }
                //接着比较当前左节点与覆盖后的右节点,如果左节点比覆盖后的小
                if (left <= coveredRight) {
                    maxRight = Math.max(maxRight, right);
                }else {
                    //如果当前线段左节点比前面的右节点大,合并次数+1,合并后,更新maxRight和coveredRight
                    total++;
                    maxRight = right;
                    coveredRight = right;
                }

            }

        }
        if (maxRight > coveredRight) {
            total++;
        }
        System.out.println(total);


    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值