Find available reservation time slots
Company: Pinterest
Role: Data Scientist
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Onsite
Quick Answer: This question evaluates a candidate's ability to reason about time-interval data and temporal normalization, testing competencies in interval manipulation, conflict detection, and algorithmic problem-solving for scheduling contexts.
Constraints
- 0 <= number of days in `hours` <= 7
- 0 <= total number of reservations across all days <= 10^4
- Each day in `hours` has exactly one opening interval with open_time < close_time
- Each reservation has start_time < end_time before clamping
- `duration` is either `None` or an integer between 1 and 1440
Examples
Input: ({'Mon': ['11:00', '22:00'], 'Tue': ['11:00', '22:00']}, {'Mon': [['12:00', '12:30'], ['18:00', '19:15']], 'Tue': []})
Expected Output: {'Mon': [['11:00', '12:00'], ['12:30', '18:00'], ['19:15', '22:00']], 'Tue': [['11:00', '22:00']]}
Explanation: Monday has two blocked intervals, so the free time is before, between, and after them. Tuesday has no reservations, so the whole opening interval is free.
Input: ({'Wed': ['09:00', '17:00']}, {'Wed': [['13:00', '14:00'], ['09:30', '10:30'], ['10:30', '11:00'], ['12:00', '13:30'], ['08:00', '09:15']]})
Expected Output: {'Wed': [['09:15', '09:30'], ['11:00', '12:00'], ['14:00', '17:00']]}
Explanation: The reservations are unsorted. After clamping and merging, the blocked intervals are [09:00, 09:15], [09:30, 11:00], and [12:00, 14:00]. The gaps between them are the available slots.
Input: ({'Fri': ['10:00', '15:00']}, {'Fri': [['10:30', '11:00'], ['12:00', '12:20'], ['13:00', '14:30']]}, 45)
Expected Output: {'Fri': [['11:00', '12:00']]}
Explanation: The free intervals are [10:00, 10:30], [11:00, 12:00], [12:20, 13:00], and [14:30, 15:00]. Only [11:00, 12:00] is at least 45 minutes long.
Input: ({'Sat': ['18:00', '20:00'], 'Sun': ['09:00', '12:00']}, {'Sat': [['17:00', '19:00'], ['18:30', '21:00']], 'Sun': [['09:00', '12:00']]})
Expected Output: {'Sat': [], 'Sun': []}
Explanation: Saturday's reservations overlap and together cover the full opening interval after clamping. Sunday's single reservation covers the whole day.
Input: ({'Thu': ['09:00', '10:00'], 'Fri': ['09:00', '10:00']}, {'Thu': [['09:15', '09:45']]})
Expected Output: {'Thu': [['09:00', '09:15'], ['09:45', '10:00']], 'Fri': [['09:00', '10:00']]}
Explanation: Thursday has one reservation, creating two free gaps. Friday is missing from `reservations`, so it is treated as having no reservations.
Input: ({}, {})
Expected Output: {}
Explanation: If there are no opening hours, there are no days to report.
Solution
def solution(hours, reservations, duration=None):
def to_minutes(value):
if isinstance(value, int):
return value
h, m = value.split(':')
return int(h) * 60 + int(m)
def to_hhmm(minutes):
return f"{minutes // 60:02d}:{minutes % 60:02d}"
min_duration = 0 if duration is None else duration
available = {}
for day, window in hours.items():
open_time = to_minutes(window[0])
close_time = to_minutes(window[1])
if open_time >= close_time:
available[day] = []
continue
blocked = []
for start, end in reservations.get(day, []):
s = to_minutes(start)
e = to_minutes(end)
if e <= open_time or s >= close_time:
continue
s = max(s, open_time)
e = min(e, close_time)
if s < e:
blocked.append([s, e])
blocked.sort()
merged = []
for s, e in blocked:
if not merged or s > merged[-1][1]:
merged.append([s, e])
else:
merged[-1][1] = max(merged[-1][1], e)
free = []
current = open_time
for s, e in merged:
if current < s and s - current >= min_duration:
free.append([to_hhmm(current), to_hhmm(s)])
current = max(current, e)
if current < close_time and close_time - current >= min_duration:
free.append([to_hhmm(current), to_hhmm(close_time)])
available[day] = free
return availableTime complexity: O(R log R), where R is the total number of reservations across all days. Space complexity: O(R).
Hints
- For each day, sort the reservations by start time and merge any intervals that overlap or touch.
- After merging, walk from opening time to closing time and collect the gaps between blocked intervals.