问题描述
强大的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()); // 输出结果
}
}