You are building a scheduling system for a company that needs to allocate conference rooms efficiently. Given a collection of meeting time intervals where each interval is represented as [start, end], determine the minimum number of conference rooms required to accommodate all meetings without any scheduling conflicts.
Each meeting occupies a room from its start time (inclusive) to its end time (exclusive). For example, a meeting from [0, 30] means the room is occupied from time 0 up to (but not including) time 30.
[start, end] where 0 ≤ start < end ≤ 1,000,000Example 1:
` Input: [[0, 30], [5, 10], [15, 20]] Output: 2 Explanation:
Example 2:
Input: [[7, 10], [2, 4]] Output: 1 Explanation: The meetings don't overlap, so 1 room is sufficient.
Example 3:
Input: [[1, 10], [2, 6], [3, 5], [7, 9]] Output: 3 Explanation: At time 3, three meetings are happening simultaneously: [1,10], [2,6], and [3,5].
Hint 1: Think About Events Instead of thinking about meetings as intervals, consider them as separate start and end events. What happens at each event in chronological order?
Hint 2: Tracking Active Meetings The answer is the maximum number of meetings happening at the same time. Can you track how many meetings are "active" as you process events chronologically?
Hint 3: Min-Heap Approach Sort meetings by start time. Use a min-heap to track end times of ongoing meetings. When starting a new meeting, remove all meetings from the heap that have already ended. The heap size tells you how many rooms are currently in use.
Full Solution `` Alternative Solution: Event-Based Sweep Line
` def minMeetingRooms(meetings): """ Event-based approach: track start and end events separately.
Time: O(n log n) Space: O(n) """ if not meetings: return 0 # Create separate lists for start and end times starts = sorted([m[0] for m in meetings]) ends = sorted([m[1] for m in meetings]) rooms_needed = 0 max_rooms = 0 start_ptr = 0 end_ptr = 0 # Process all events in chronological order while start_ptr < len(meetings): if starts[start_ptr] < ends[end_ptr]: # A meeting starts - need another room rooms_needed += 1 max_rooms = max(max_rooms, rooms_needed) start_ptr += 1 else: # A meeting ends - free up a room rooms_needed -= 1 end_ptr += 1 return max_rooms`
Complexity Analysis:
- Time Complexity: O(n log n) where n is the number of meetings. Dominated by sorting the meetings or event times.
- Space Complexity: O(n) for the heap (min-heap approach) or for storing start/end times separately (sweep line approach).
Key Insights:
- The answer equals the maximum number of overlapping meetings at any point in time
- Sorting by start time allows us to process meetings in chronological order
- A min-heap efficiently tracks which meetings are currently active by their end times
- The sweep line approach processes start and end events separately, counting active meetings
import heapq
def minMeetingRooms(meetings):
"""
Calculate minimum conference rooms needed using a min-heap.
Approach:
1. Sort meetings by start time
2. Use a min-heap to track end times of ongoing meetings
3. For each meeting, remove ended meetings from heap
4. Add current meeting's end time to heap
5. Track maximum heap size (concurrent meetings)
Time: O(n log n) - sorting + heap operations
Space: O(n) - heap storage
"""
if not meetings:
return 0
# Sort meetings by start time
meetings.sort(key=lambda x: x[0])
# Min-heap to track end times of ongoing meetings
end_times = []
max_rooms = 0
for start, end in meetings:
# Remove all meetings that have ended before current start time
while end_times and end_times[0] <= start:
heapq.heappop(end_times)
# Add current meeting's end time
heapq.heappush(end_times, end)
# Track maximum concurrent meetings
max_rooms = max(max_rooms, len(end_times))
return max_rooms