题目分析
- 按照常识,要根据开始时间来排序,先开的排在前面
- 前面有会议开完,则可以利用该会议室;否则,要新开一间会议室
Solution - 最小堆
- 最小堆,取最小值:O(1);插入,删除:O(logn)
- 堆顶:最早开的会的结束时间,这样要开的会的开始时间和最早结束的会议的结束时间比较
- 最后堆中,剩下的元素个数为所需要的会议室,即没有在要开的会了
public int minMeetingRooms(int[][] intervals) {
if (intervals == null || intervals.length == 0) return 0;
// 按照会议的开始时间,从小到大排序 nlogn
Arrays.sort(intervals, (m1, m2) -> m1[0] - m2[0]);
// 创建一个最小堆(存放每一个会议的结束时间)
PriorityQueue<Integer> heap = new PriorityQueue<>();
// 添加0号会议的结束时间
heap.add(intervals[0][1]);
// 堆顶的含义:目前占用的会议室中最早结束的时间
for (int i = 1; i < intervals.length; i++) { // nlogn
// i号会议的开始时间 >= 堆顶
if (intervals[i][0] >= heap.peek()) {
heap.remove();
}
// 将i号会议的结束时间加入堆中
heap.add(intervals[i][1]);
}
return heap.size();
}
Solution - 分开排序
- 开始时间排序 --> 最小堆前的排序 --> 即按照会议开始时间排序
- 结束时间排序 --> 最小堆排序 --> 目前最早结束时间
public int minMeetingRooms(int[][] intervals) {
if (intervals == null || intervals.length == 0) return 0;
// 存放所有会议的开始时间
int[] begins = new int[intervals.length];
// 存放所有会议的结束时间
int[] ends = new int[intervals.length];
for (int i = 0; i < intervals.length; i++) {
begins[i] = intervals[i][0];
ends[i] = intervals[i][1];
}
// 排序
Arrays.sort(begins);
Arrays.sort(ends);
int room = 0, endIdx = 0;
for (int begin : begins) {
if (begin >= ends[endIdx]) { // 能重复利用会议室
endIdx++;
} else { // 需要新开一个会议室
room++;
}
}
return room;
}
Reference:小码哥MJ