这两道题来自Leetcode 252 和Leetcode253 ,需要会员才能做!!
1.1 会议室I
思路很简单,对会议按照开始时间进行排序,如果后一个会议的开始时间小于前一个会议的结束时间,则表示这两个会议冲突,不能都参加
public static boolean scheduleMeetingRoom1(int[][] meetings){
if(meetings == null || meetings.length == 0) return false;
Arrays.sort(meetings, (a,b) -> a[0] - b[0]);
for(int i = 1; i < meetings.length; i++){
if(meetings[i][0] < meetings[i-1][1]) return false;
}
return true;
}
1.2 会议室II
解法1: 排序 + 小顶堆 ,时间复杂度N*log(N),空间复杂度O(n)
贪心思想
- 先把会议室按照开始时间进行排序,用堆存放正在进行的会议的结束时间
- 然后遍历每一个会议,把会议的开始时间与正在进行的会议的最早结束时间进行比较,
- 如果当前会议的开始时间大于等于进行中的会议的最早结束时间,那么就可以复用那个会议室,移除之前堆中最早结束的会议,把当前会议的结束时间放到堆中
- 否则新开一个会议室,
- 遍历完所有会议,堆的大小就是需要的会议室
public static int scheduleMeetingRoom2(int[][] meetings){
if(meetings == null || meetings.length == 0) return 0;
Arrays.sort(meetings, (a,b) -> a[0] - b[0]);//N*log(N)
//创建一个最小堆,存放每一个会议的结束时间
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();//空间复杂度O(N)
priorityQueue.add(meetings[0][1]);
for(int i = 1; i < meetings.length; i++){ //N*log(N)
if(meetings[i][0] >= priorityQueue.peek()) priorityQueue.poll();
priorityQueue.add(meetings[i][1]);
}
return priorityQueue.size();
}
解法2: 既然堆的作用是对会议的结束时间进行排序,那我们可以使用数组来代替堆
- 分别对开始时间和结束时间进行排序,遍历开始时间数组
- 如果开始时间大于等于结束时间数组中最小值,代表可以复用,endIdx++,beginIdx++
- 否则,代表不能复用,所需要的会议室room++,beginIdx++
public static int scheduleMeetingRoom3(int[][] meetings){
//贪心思想
//和解法2类似,只是把堆换成了数组,用数组来保存结束时间,并对数组排序可以达到和使用堆一样的效果
if(meetings == null || meetings.length == 0) return 0;
int [] begins = new int[meetings.length];
int [] ends = new int[meetings.length];
for (int i = 0; i < meetings.length; i++) {
begins[i] = meetings[i][0];
ends[i] = meetings[i][1];
}
Arrays.sort(begins);
Arrays.sort(ends);
int eindex = 0;
int room = 0;
for (int begin : begins) {
if(begin >= ends[eindex]) eindex++;
else room++;
}
return room;
}