Find earliest common meeting slot
Company: Citadel
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Technical Screen
Quick Answer: This question evaluates proficiency with interval manipulation, timeline merging, and algorithmic reasoning for scheduling constraints, measuring competency in handling sorted interval lists, edge-case sanitization, and complexity analysis.
Constraints
- 1 <= len(calendars) == len(work_windows) <= 100000
- 0 <= total number of busy intervals across all calendars <= 200000
- 0 <= start < end <= 1440
- 0 <= workStart < workEnd <= 1440
- 1 <= d <= 1440
Examples
Input: ([[[540, 570], [630, 660]], [[555, 585], [615, 645]], [[600, 615]]], [[480, 720], [540, 690], [510, 660]], 15)
Expected Output: [585, 600]
Explanation: The common working window is [540, 660). After merging busy times across all three calendars, the first free gap of length 15 is [585, 600).
Input: ([[[540, 600], [620, 660]], [[530, 610]], [[600, 650]]], [[540, 660], [540, 660], [540, 660]], 10)
Expected Output: []
Explanation: All busy intervals merge to cover the entire common working window [540, 660), so no 10-minute slot exists.
Input: ([[[100, 130], [90, 110], [150, 160]], [[80, 95], [125, 140]]], [[80, 170], [70, 170]], 10)
Expected Output: [140, 150]
Explanation: Normalize the first calendar to [90, 130) and [150, 160). After merging both participants' busy times, the first 10-minute gap is [140, 150).
Input: ([[], []], [[480, 540], [500, 560]], 20)
Expected Output: [500, 520]
Explanation: The common working window is [500, 540) and nobody is busy, so the earliest 20-minute slot starts at 500.
Input: ([[], []], [[100, 120], [130, 150]], 5)
Expected Output: []
Explanation: The participants' working windows do not overlap, so there is no common time to meet.
Input: ([[[10, 20], [20, 30]], [[0, 15], [35, 40]]], [[0, 50], [0, 50]], 5)
Expected Output: [30, 35]
Explanation: Adjacent busy intervals [10, 20) and [20, 30) leave no free gap at 20. After merging all busy time, the first 5-minute gap is [30, 35).
Solution
def solution(calendars, work_windows, d):
import heapq
if not calendars or not work_windows or len(calendars) != len(work_windows):
return []
common_start = max(window[0] for window in work_windows)
common_end = min(window[1] for window in work_windows)
if common_end - common_start < d:
return []
def normalize(calendar):
intervals = []
for interval in calendar:
if len(interval) != 2:
continue
start, end = interval
if end <= start:
continue
intervals.append((start, end))
intervals.sort()
merged = []
for start, end in intervals:
if not merged or start > merged[-1][1]:
merged.append([start, end])
elif end > merged[-1][1]:
merged[-1][1] = end
clipped = []
for start, end in merged:
start = max(start, common_start)
end = min(end, common_end)
if start < end:
clipped.append([start, end])
return clipped
normalized = [normalize(calendar) for calendar in calendars]
heap = []
for person, calendar in enumerate(normalized):
if calendar:
start, end = calendar[0]
heapq.heappush(heap, (start, end, person, 0))
if not heap:
return [common_start, common_start + d]
current = common_start
while heap:
start, end, person, idx = heapq.heappop(heap)
next_idx = idx + 1
if next_idx < len(normalized[person]):
next_start, next_end = normalized[person][next_idx]
heapq.heappush(heap, (next_start, next_end, person, next_idx))
if end <= current:
continue
if start - current >= d:
return [current, current + d]
current = max(current, end)
while heap and heap[0][0] <= current:
start2, end2, person2, idx2 = heapq.heappop(heap)
next_idx2 = idx2 + 1
if next_idx2 < len(normalized[person2]):
next_start2, next_end2 = normalized[person2][next_idx2]
heapq.heappush(heap, (next_start2, next_end2, person2, next_idx2))
if end2 > current:
current = end2
if common_end - current >= d:
return [current, current + d]
return []Time complexity: O(sum(m_i log m_i) + M log K), where m_i is the size of calendar i and M is the total number of busy intervals after preprocessing. If calendars are already sorted and non-overlapping, preprocessing drops to O(M).. Space complexity: O(M + K).
Hints
- Any valid meeting must lie inside the intersection of all participants' working windows.
- After clipping busy intervals to that common window, treat each calendar as a sorted stream and merge the K streams with a min-heap instead of flattening everything when K is large.