解法一:陣列排序
思路
將回憶間隔分為開始和結束兩個陣列,按照從小到大順序排序。要尋找一個會議開始時間是否和其他會議的最早結束時間衝突。
那麼,如果一個會議的開始時間在最早結束時間前開始,就需要一個房間,反之可以在其後面進行會議。如果一個會議開始時間大於最早結束時間,不需要額外房間,但最早的結束時間需要向後移動一個位置。
舉例:如 start = [1,3,5,15,35]; end = [9, 11, 26, 30, 33]
那麼1,3,5都在最早結束時間9的前面,所以都需要額外房間。此時房間數為3。15在9後面,所以不用額外安排時間,而最早結束時間變為11。35在11後面,所以也不用額外安排房間。所以總的房間數為3。
程式碼
class Solution {
public int minMeetingRooms(int[][] intervals) {
/*
Sepearate the start and end to two arrays and sort them by ascending order
Assign the earlist end time to be end[0];
Initialize num of room = 0;
for each start time
if (start time > end time)
earlist end time move to next end[];
else
num++
end if
end for each
*/
int len = intervals.length;
// 首先想到陣列為空的情況
if (len == 0 || intervals == null) return 0;
int[] start = new int[len];
int[] end = new int[len];
for (int i = 0; i < len; i++) {
start[i] = intervals[i][0];
end[i] = intervals[i][1];
}
Arrays.sort(start);
Arrays.sort(end);
int earlistIndex = 0;
int num = 0;
for (int i = 0; i < len; i++) {
if (start[i] >= end[earlistIndex]) { // 要注意 edge case, 開始時間和結束時間相等也不用額外安排房間
earlistIndex++;
}
else {
num++;
}
}
return num;
}
}
時間複雜度:O(nlogn),因為排序花費O(nlogn),遍歷開始時間花費O(n)。
空間複雜度: O(n), 因為使用了兩個陣列去儲存時間。
解法二:MinHeap
思路
依然是將元素按開始時間排序,並比較之前會議的最早結束時間是否與當前會議的開始時間重合。
將陣列中元素按照開始時間從大到小排序;
定義一個PriorityQueue,按照結束時間從小到大儲存intervals;
從已經排序的陣列中取出間隔,如果開始時間和最早結束時間重合,存入PriorityQueue中;
否則,將最早結束時間擴散至當前會議的結束時間。
程式碼
class Solution {
public int minMeetingRooms(int[][] intervals) {
int len = intervals.length;
if (len == 0 || intervals == null) {
return 0;
}
Arrays.sort(intervals, new Comparator<int[]>(){
public int compare(int[] a, int[]b) {
return a[0] - b[0];
}
});
PriorityQueue<int[]> minHeap = new PriorityQueue<>(intervals.length, new Comparator<int[]>(){
public int compare (int[] a, int[]b) {
return a[1] - b[1];
}
});
minHeap.offer(intervals[0]);
// Start from the next element because the first one is already in the heap.
for (int i = 1; i < len; i ++) {
int[] earlistEnding = minHeap.poll();
// No overlap, append the ending time
if (intervals[i][0] >= earlistEnding[1]) {
earlistEnding[1] = intervals[i][1];
}
// Overlap, add a new room
else
{
minHeap.offer(intervals[i]);
}
minHeap.offer(earlistEnding);
}
return minHeap.size();
}
}
時間複雜度 O(nlogn), 空間複雜度 O(n)。
Takeaway
- 注意空陣列情況和 edge cases。
- PriorityQueue 的使用:
- 建立:
PriorityQueue<Integer> p = new PriorityQueue<>(); // 預設最小值在頭部
- 使用:poll():彈出頭部的元素;offer():新增新的元素,按照規定的排序順序排列。
- 建立:
- 自定義排序順序
- Override (標準方法)
PriorityQueue<int[]> q = new PriorityQueue<>(size, new Comaprator<int[]>(){ public int new comapre(int[] a, int[] b){ return a[1] - b[1]; } });
- lamda 表示式(簡化方法)
PriorityQueue<int[]> q = new PriorityQueue<>(size, (int[] a, int[] b)->(a[1] - b[1]));
- Override (標準方法)
本作品採用《CC 協議》,轉載必須註明作者和本文連結