试题 算法训练 藏匿的刺客 (Java 贪心)

问题描述
  强大的kAc建立了强大的帝国,但人民深受其学霸及23文化的压迫,于是勇敢的鹏决心反抗。
  kAc帝国防守森严,鹏带领着小伙伴们躲在城外的草堆叶子中,称为叶子鹏。
  kAc帝国的派出的n个看守员都发现了这一问题,第i个人会告诉你在第li个草堆到第ri个草堆里面有人,要求你计算所有草堆中最少的人数,以商议应对。
  “你为什么这么厉害”,得到过kAc衷心赞美的你必将全力以赴。
输入格式
  第一行一个数字n,接下来2到n+1行,每行两个数li和ri,如题。
输出格式
  输出一个数,表示最少人数。
  
样例输入
5
2 4
1 3
5 7
1 8
8 8

样例输出
3

数据规模和约定
  30%的数据n<=10
  70%的数据n<=100
  100%的数据n<=1000
  所有数字均在int表示范围内

对于贪心算法,几乎都是需要排序的,只是排序的方式多种多样,有时候去暴力排序很麻烦,复杂度也很高,此时我们可以去自定义排序方法,Java中可以用Comparator中的compare来自定义排序方法,我也才接触它第二天,我就不多解释它的用法,小伙伴可以自行查阅资料去了解。

本题思路:
本题跟活动安排问题很相似,将区间按右端点排序,只是活动安排是找不重合的区间,这里是合并重合的区间,并,删掉合并前的两个区间,需要注意的是,合并的时候必须合并连续且重合的区间,若重合,但不连续,可能会得到错误的答案,例如:
在这里插入图片描述

完整代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
class grass{    //  定义区间对象
    int left;
    int right;
    public grass(int a,int  b){
        left = a;
        right = b;
    }
}
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(reader.readLine());
        List<grass> list = new ArrayList<>();   //  新建List集合来保存区间
        for (int i=0;i<n;i++){
            String[] num = reader.readLine().trim().split(" ");
            int a = Integer.parseInt(num[0]);   //  将区间存入集合
            int b = Integer.parseInt(num[1]);
            list.add(new grass(a,b));
        }
        list.sort(new Comparator<grass>() {
            @Override
            public int compare(grass o1, grass o2) {    //  定义排序方法,按右端点大小排序
                return o1.right-o2.right;
            }
        });
        int i=0;
        while (i<list.size()-1){	//	下面的操作是,从当前开始,若下一个区间跟本区间重合,则合并,不重合则判断下一个
            if (list.get(i).right>list.get(i+1).left){  //  合并连续的区间
                int r = list.get(i).right;
                int l = Math.max(list.get(i).left, list.get(i + 1).left);
                list.set(0,new grass(l,r)); // 修改区间后将新的区间放入集合
                list.remove(i+1);   //  把多余的区间删除
            }	//	若重合,i值应不变,表示当前合并后的区间,不重合才使i指向下一个
            else i++;   //  控制结束的符号
        }	
        System.out.println(list.size());    //  输出结果
    }
}
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Easenyang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值