Given the availability time slots arrays slots1
and slots2
of two people and a meeting duration duration
, return the earliest time slot that works for both of them and is of duration duration
.
If there is no common time slot that satisfies the requirements, return an empty array.
The format of a time slot is an array of two elements [start, end]
representing an inclusive time range from start
to end
.
It is guaranteed that no two availability slots of the same person intersect with each other. That is, for any two time slots [start1, end1]
and [start2, end2]
of the same person, either start1 > end2
or start2 > end1
.
Example 1:
Input: slots1 = [[10,50],[60,120],[140,210]], slots2 = [[0,15],[60,70]], duration = 8 Output: [60,68]Example 2:
Input: slots1 = [[10,50],[60,120],[140,210]], slots2 = [[0,15],[60,70]], duration = 12 Output: []
Constraints:
1 <= slots1.length, slots2.length <= 10^4
slots1[i].length, slots2[i].length == 2
slots1[i][0] < slots1[i][1]
slots2[i][0] < slots2[i][1]
0 <= slots1[i][j], slots2[i][j] <= 10^9
1 <= duration <= 10^6
安排会议日程。
题意是给两个人的日程表和一个duration时长,日程表以区间表示,请返回两个人有可能有机会进行一次时长为duration的会议的interval是什么。打个比方,比如第一个例子,两人要开一个时长为8分钟的会议,两人的日程如下,结果返回的是60 - 68分钟两人都有时间开会。
这个题不需要考虑一些invalid的case诸如interval的开始时间大于interval的结束时间,所以会好处理一些。思路依然是经典的扫描线。discussion里面目前最高票的答案 [4.4.2020] 给的是priority queue的做法。他的思路是去掉两人各自无效的interval(interval本身小于会议时间duration的)之后,把两人所有有效的interval加入pq,pq是按interval的开始时间排序的。先弹出一个interval,比较这个interval的结束时间[1] 是否大于等于堆顶interval[0] + duration。这个思路利用到了题目中给的最后一句话,就是对于同一个人来说,他的duration一定不会互相有交集。那么在从pq弹出的时候,如果有两个intervals能有交集且满足duration,那么说明这两个intervals一定来自不同的人。
时间O(nlogn) - sort
空间O(1)
Java实现 - pq思路
1 class Solution { 2 public List<Integer> minAvailableDuration(int[][] slots1, int[][] slots2, int duration) { 3 PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparing(a -> a[0])); 4 for (int[] s : slots1) { 5 if (s[1] - s[0] >= duration) { 6 pq.offer(s); 7 } 8 } 9 for (int[] s : slots2) { 10 if (s[1] - s[0] >= duration) { 11 pq.offer(s); 12 } 13 } 14 while (pq.size() > 1) { 15 if (pq.poll()[1] >= pq.peek()[0] + duration) { 16 return Arrays.asList(pq.peek()[0], pq.peek()[0] + duration); 17 } 18 } 19 return Arrays.asList(); 20 } 21 }
我再提供一个非pq的做法。先将两个人的intervals按照开始时间排序,之后用双指针分别遍历两个人的intervals,同时找这个可能的interval的start和end分别在哪,如果满足start + duration <= end则记录当前的start和end。如果没有这样的case就返回空的list。
Java实现 - mergesort思路
1 class Solution { 2 public List<Integer> minAvailableDuration(int[][] slots1, int[][] slots2, int duration) { 3 Arrays.sort(slots1, (a, b) -> a[0] - b[0]); 4 Arrays.sort(slots2, (a, b) -> a[0] - b[0]); 5 int i = 0; 6 int j = 0; 7 int m = slots1.length; 8 int n = slots2.length; 9 while (i < m && j < n) { 10 int intersectionStart = Math.max(slots1[i][0], slots2[j][0]); 11 int intersectionEnd = Math.min(slots1[i][1], slots2[j][1]); 12 if (intersectionStart + duration <= intersectionEnd) { 13 return Arrays.asList(intersectionStart, intersectionStart + duration); 14 } else if (slots1[i][1] < slots2[j][1]) { 15 i++; 16 } else { 17 j++; 18 } 19 } 20 return new ArrayList<>(); 21 } 22 }
JavaScript实现
1 /** 2 * @param {number[][]} slots1 3 * @param {number[][]} slots2 4 * @param {number} duration 5 * @return {number[]} 6 */ 7 var minAvailableDuration = function(slots1, slots2, duration) { 8 slots1.sort((a, b) => a[0] - b[0]); 9 slots2.sort((a, b) => a[0] - b[0]); 10 let m = slots1.length; 11 let n = slots2.length; 12 let i = 0; 13 let j = 0; 14 while (i < m && j < n) { 15 let start = Math.max(slots1[i][0], slots2[j][0]); 16 let end = Math.min(slots1[i][1], slots2[j][1]); 17 if (start + duration <= end) { 18 return [start, start + duration]; 19 } else if (slots1[i][1] < slots2[j][1]) { 20 i++; 21 } else { 22 j++; 23 } 24 } 25 return []; 26 };