版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)
1.题目描述
题目描述:
库特君在吃面条!
他将面条放在了数轴上,每根面条对应数轴上的两个点a和b,他想知道在任意两根面条不重叠(端点可以重叠)的情况下最多能选出多少根面条。
1 <= n <= 100
-999 <= a
输入描述:
第一行为一个整数N
接下来,N行每行N个整数a和b
输出描述:
一个数的答案
输出样例:
3 6 3 1 3 2 5
输出样例:
2
2.解题思路
贪心算法的区间调度问题
- 贪心策略:在不与已选区域重叠的前提下,优先选择右端点最小的区间,所以按照区间右端点排序后,依次检查,不重叠就选择,并更新已选区域的最右端,方便判断重叠。
算法设计:
- 如果被检查的活动i的开始时间小于最近选择的活动j的结束时间,则不选择活动i,否则选择活动i
- 1.选择最早结束的面条,便是最开始要选择的没有重叠的第一根面条
- 2.选择第一根面条结束后[右端点值]才开始的第二根面条[该面条的左端点大于等于第一根面条的右端点],并且此时右端点结束最早的面条,这将是要选择的第二根面条。
- 3.更新右端点值,重复以上。
3.代码
import java.util.*;
//贪心算法的区间调度问题
public class Main {
public static void main(String[] args) {
Scanner sr = new Scanner(System.in);
int N = sr.nextInt();
List<Work> lists = new ArrayList<>();
for(int i = 0;i<N;i++){
int x1 = sr.nextInt();
int x2 = sr.nextInt();
//题目说了x1<x2,但是给出的样例出现了问题,故用个if语句
if(x1<x2)
lists.add(new Work(x1,x2));
else
lists.add(new Work(x2,x1));
}
System.out.println(solution(lists));
}
//解决方法
private static int solution(List<Work> works) {
//works里面已经按end从小到大排序了,这时在将start进行排序,找到第一个要进行的工作
Collections.sort(works);
int count = 1;
//当前工作的结束时间
int endTime = works.get(0).getEnd();
for(int i = 1;i<works.size();i++){
// 第二根面条的开始时间大于第一个面条的结束时间
if(endTime<=works.get(i).getStart()){
//这个面条可选,没有覆盖之前的面条
count++;
//更新右端点
endTime = works.get(i).getEnd();
}
}
return count;
}
static class Work implements Comparable{
private int start;
private int end;
public Work(int start, int end) {
this.start = start;
this.end = end;
}
//end 从小到大排序
@Override
public int compareTo(Object o) {
Work work = (Work) o;
if(this.end > work.getEnd()){
return 1;
}else if(this.end == work.getEnd()){
return 0;
}else{
return -1;
}
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
}
}
题目整理自牛客技术篇
个人想法,如有错误请指出!!