|
| 1 | +# [Problem 2402: Meeting Rooms III](https://leetcode.com/problems/meeting-rooms-iii/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +- We need to allocate meetings to rooms 0..n-1 following the given rules. The meetings have unique start times; it's natural to sort by start time (or use the given unique starts to process in increasing start). |
| 5 | +- At any meeting start time s, some rooms might already be free (their meeting end <= s). We should track free rooms and busy rooms. A min-heap of free room indices (so we always pick the smallest available room id) and a min-heap of busy rooms keyed by end time (and then room id to break ties) is a common design. |
| 6 | +- If there is a free room at meeting start s, assign the lowest-numbered free room and schedule it to end at the meeting's end. |
| 7 | +- If no free room exists at start s, the meeting must be delayed until the earliest busy room frees. We should pop the earliest finishing busy room (end_time, room), compute the delayed meeting's new end = end_time + duration, and assign it to that room. Because meetings are processed in original start order, delayed meetings will be considered in the correct priority order (earlier original start first). |
| 8 | +- Maintain counts per room; at the end, return the room with the highest count (ties broken by lowest index). |
| 9 | + |
| 10 | +## Refining the problem, round 2 thoughts |
| 11 | +- Edge cases: n = 1, many meetings — all will be sequentially delayed; algorithm must correctly compute new end times. |
| 12 | +- Need to be careful about tie-breaking when multiple rooms finish at the same time: using a busy heap keyed by (end_time, room_id) ensures that when multiple rooms free simultaneously the popped room is the one with the smallest id, which matches the rule about choosing the smallest-numbered unused room. |
| 13 | +- Complexity: each meeting triggers at most a constant number of heap operations on heaps of size at most n (n <= 100), so overall time is O(m log n) where m = len(meetings). Space O(n) for heaps and counts. |
| 14 | +- Implementation detail: sort meetings by start. For each meeting (s, e): |
| 15 | + - Release any busy rooms with end_time <= s into the free heap. |
| 16 | + - If free not empty: pop smallest room, assign, push (e, room) into busy, increment count. |
| 17 | + - Else: pop earliest busy (end, room), compute new_end = end + (e - s), assign, push (new_end, room) back, increment count. |
| 18 | +- Finally, pick the room with maximum count (tie -> smallest index). |
| 19 | + |
| 20 | +## Attempted solution(s) |
| 21 | +```python |
| 22 | +import heapq |
| 23 | +from typing import List |
| 24 | + |
| 25 | +class Solution: |
| 26 | + def mostBooked(self, n: int, meetings: List[List[int]]) -> int: |
| 27 | + # Sort meetings by original start time |
| 28 | + meetings.sort(key=lambda x: x[0]) |
| 29 | + |
| 30 | + # Free rooms min-heap by room index |
| 31 | + free_rooms = list(range(n)) |
| 32 | + heapq.heapify(free_rooms) |
| 33 | + |
| 34 | + # Busy rooms min-heap by (end_time, room_index) |
| 35 | + busy = [] |
| 36 | + |
| 37 | + # Count of meetings per room |
| 38 | + counts = [0] * n |
| 39 | + |
| 40 | + for s, e in meetings: |
| 41 | + # Free any rooms that have finished by time s |
| 42 | + while busy and busy[0][0] <= s: |
| 43 | + end_time, room = heapq.heappop(busy) |
| 44 | + heapq.heappush(free_rooms, room) |
| 45 | + |
| 46 | + duration = e - s |
| 47 | + if free_rooms: |
| 48 | + # assign lowest-numbered free room |
| 49 | + room = heapq.heappop(free_rooms) |
| 50 | + counts[room] += 1 |
| 51 | + heapq.heappush(busy, (e, room)) |
| 52 | + else: |
| 53 | + # no free rooms: delay until earliest room frees |
| 54 | + end_time, room = heapq.heappop(busy) |
| 55 | + # meeting starts at end_time and lasts 'duration' |
| 56 | + new_end = end_time + duration |
| 57 | + counts[room] += 1 |
| 58 | + heapq.heappush(busy, (new_end, room)) |
| 59 | + |
| 60 | + # find room with highest count (tie -> lowest index) |
| 61 | + best_room = 0 |
| 62 | + for i in range(1, n): |
| 63 | + if counts[i] > counts[best_room]: |
| 64 | + best_room = i |
| 65 | + return best_room |
| 66 | +``` |
| 67 | +- Notes: |
| 68 | + - Approach: sort by start time, use two heaps: free_rooms (min room index) and busy (min end time, then room index). For each meeting free any rooms that have finished by its start, otherwise delay by popping earliest busy room and scheduling the meeting to start at that end time. |
| 69 | + - Complexity: Time O(m log n) where m = number of meetings and n <= 100 (heap ops cost log n). Space O(n) for the heaps and counts. |
| 70 | + - Important detail: busy heap stores tuples (end_time, room) so when multiple rooms free at the same end time, the one with smaller room id is popped first (tie-breaker), which matches requirement to use the smallest-numbered unused room. The processing order (sorted original starts) ensures delayed meetings are awarded rooms in order of original start times. |
0 commit comments