Katkat

Find Common Free Time Slots Across Calendars

GoogleSoftware Engineer · Onsite

Last updated

Tests your ability to process and merge multiple sets of time intervals to find mutually available time windows within a given working day.

Problem Statement

You are building a scheduling tool to find mutually agreeable meeting times for a group of colleagues. You are given the busy schedules of n people, where each person's schedule is represented as a list of non-overlapping, sorted time intervals [start, end]. Time is represented as integers (for example, minutes past midnight).

You are also given a global working window [day_start, day_end] and a minimum required meeting duration duration.

Write a function to return all common time slots during which everyone is free for at least duration minutes. The returned slots should be within [day_start, day_end], inclusive, sorted chronologically, and non-overlapping.

Function Signature

def find_common_free_slots(
    schedules: list[list[list[int]]],
    working_hours: list[int],
    duration: int
) -> list[list[int]]:
    pass

Input & Output Format

  • schedules: A list of lists of intervals. schedules[i] is a list of [start, end] pairs representing busy intervals for person i.
  • working_hours: A list of two integers [day_start, day_end] denoting the daily working window.
  • duration: A positive integer representing the minimum length of free time needed.
  • Return: A list of intervals [start, end] where all people are free and end - start >= duration.

Examples

Example 1

Input:
schedules = [
    [[90, 150], [180, 240]],
    [[120, 160], [270, 330]]
]
working_hours = [60, 360]
duration = 30

Output:
[[60, 90], [240, 270], [330, 360]]

Explanation: The combined busy intervals clipped to [60, 360] are [90, 160], [180, 240], and [270, 330]. The free gaps between these and the boundaries are [60, 90], [160, 180], [240, 270], and [330, 360]. Only gaps of at least 30 minutes are returned ([160, 180] is 20 minutes, so it is omitted).

Example 2

Input:
schedules = [
    [[0, 300]]
]
working_hours = [100, 200]
duration = 15

Output:
[]

Explanation: The person is busy for the entire working window [100, 200], so no slots are available.

Constraints

  • 1 <= len(schedules) <= 100
  • Total number of busy intervals across all people <= 10^4
  • 0 <= day_start < day_end <= 24 * 60 (or up to 10^6)
  • 1 <= duration <= day_end - day_start
  • For each interval [start, end]: start < end

Edge Cases

  • Empty schedules (all participants are completely free).
  • Intervals that fall partially or completely outside [day_start, day_end].
  • Consecutive busy intervals touching at endpoints (e.g., [100, 150] and [150, 200] should merge into [100, 200]).

Hints

Hint 1

Rather than finding free times person-by-person and intersecting them, consider pooling all busy intervals across all participants.

Hint 2

Sort and merge all busy intervals into a single non-overlapping set of blocked times, clamping each interval to [day_start, day_end].

Hint 3

Once the combined busy intervals are merged, the free times are simply the gaps between consecutive busy intervals that satisfy the duration requirement.

Follow-up questions

  • How would you optimize the solution if each person's schedule is already sorted and you want to avoid flattening and re-sorting all intervals?
  • How would you modify your approach if some participants are marked as 'optional' and you want to maximize attendance rather than requiring 100% availability?
  • How would you handle this in a real-time system where busy events are streamed or updated concurrently?