题目一:给你一个数组
events
,其中events[i] = [startDayi, endDayi]
,表示会议i
开始于startDayi
,结束于endDayi
。你可以在满足
startDayi <= d <= endDayi
中的任意一天d
参加会议i
。注意,一天只能参加一个会议。请你返回你可以参加的 最大 会议数目。
记录题解:
贪心思路:按照会议结束时间最小的优先排,因为结束时间靠后的 “战线” 拉的长,可以排后面,前面的天数可以让给结束时间短的会议优先排
大白画:统计当天为起始时间的所有会议,选取其中结束时间最早的那个会议
首先需要按照起始时间对 events 数组进行升序排列,使得起始时间相同的会议放在一起,避免后面在统计当天为起始时间的会议时,每统计一天,都要对 events 数组进行遍历。排序后,我们可以维护一个变量,遍历并标记 events 的位置,使得 events 在统计完所有天的会议后之遍历一遍。
这里需要维护动态变化(考虑到过期会议)的结束时间的最小值,可以使用小顶堆来维护。
过期会议:可能已经有未排的会议的结束时间在当天之前,这时我们需要将过期会议的结束时间从小顶堆中移除。
class Solution {
public int maxEvents(int[][] events) {
int res = 0;
PriorityQueue<Integer> pq = new PriorityQueue<>();
Arrays.sort(events,new Comparator<int[]>(){
public int compare(int[] a1,int[] a2){
return a1[0] - a2[0];
}
});
int i = 0, n = events.length,curDay = 1;
while(i < n || !pq.isEmpty()){
//将curDay这一天为起始时间的会议加入优先级队列
while(i < n && curDay <= events[i][1] && curDay >= events[i][0]){
pq.offer(events[i][1]);
i++;
}
//移除过期的
while(!pq.isEmpty() && curDay > pq.peek()){
pq.poll();
}
//从剩下的选出结束时间最小的作为curDay 的会议
if(pq.peek() != null){
res++;
pq.poll();
}
//选下一天的会议
curDay++;
}
return res;
}
}
注:java 中 PriorityQueue (优先级队列)默认就是小顶堆结构
题目二:一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。给你一个项目开始的时间(给你一个数组,里面是一个个具体的项目), 你来安排宣讲的日程,要求会议室进行的宣讲的场次最多。返回最多场次
class Event{
public int start;//会议开始时间
public int end;//会议结束时间
}
class Greedy{
public int bestArrange(Event[] events){
//按结束时间排序
int res = 0;
int temp = 0;
Arrays.sort(events,new Comparator<Event>(){
public int compare(Event e1,Event e2){
return e1 - e2;
}
});
for(int i = 0; i < events.length; i++){
//判断一下个会议是否过期,这里不同于第一题,第一题时一个会议开一天,此题会议的持续时间不定,是某一个时间段,所以要判断star会议起始时间是否过期
if(temp <= events[i + 1].start){
res++;
temp = events[i + 1].end;
}
}
return res;
}
}