Level 1 Book the first free room
An office has a fixed set of meeting rooms, each with a unique string id. Build MeetingScheduler, which hands out rooms for meetings:
MeetingScheduler(room_ids: list[str]): the rooms, in any order (at least one, all ids distinct).book(start: int, end: int) -> str | None: reserve a room for the half-open interval[start, end)and return its id. Among all rooms that are free for the whole interval, pick the one whose id is smallest in string order ("room10" < "room2"). If no room is free, book nothing and returnNone.schedule(room_id: str) -> list[tuple[int, int]]: the meetings booked in that room, as(start, end)pairs sorted by start.room_idis always one of the rooms.
Intervals are half-open, so a meeting ending at 20 and one starting at 20 don't clash. Times are integers with 0 <= start < end <= 10**9.
s = MeetingScheduler(["b", "a"])
s.book(10, 20) # "a"
s.book(15, 25) # "b" ("a" is busy from 15 to 20)
s.book(20, 30) # "a" (back-to-back with 10-20 is fine)
s.book(12, 18) # None (both rooms are busy at 15)
s.schedule("a") # [(10, 20), (20, 30)]
s.schedule("b") # [(15, 25)]
A room may collect tens of thousands of meetings. Checking whether one room is free must take O(log n) in that room's number of meetings, not a scan of all of them.
Show hint
The meetings in one room never overlap, so if you keep them sorted by start, their ends are sorted too. Binary-search for the last meeting that starts before end; the room is free exactly when that meeting (if any) ends at or before start.