Meeting Rooms II
Medium · Intervals · Explanation and code example
Greedy
How it works
We want to find the minimum number of meeting rooms required so that no meetings overlap.
Instead of thinking in terms of rooms directly, we can think in terms of events on a timeline:
- when a meeting starts, we need one more room
- when a meeting ends, one room is freed
So the problem reduces to:
What is the maximum number of meetings happening at the same time?
If we track how the number of active meetings changes over time, the maximum value we ever reach is exactly the number of rooms we need.
This greedy approach works by:
- converting each meeting into two events (start and end)
- sorting all events by time
- sweeping from left to right while counting active meetings
Steps
- Create an empty list
timeto store events. - For each meeting interval:
- add
(start, +1)→ meeting starts (need a room) - add
(end, -1)→ meeting ends (free a room)
- add
- Sort
time:- primarily by time
- secondarily by event type so that end events (
-1) are processed before start events (+1) at the same time
- Initialize:
count=0→ current number of ongoing meetingsres=0→ maximum number of rooms needed
- Traverse the sorted
timelist:- add the event value (
+1or-1) tocount - update
res=max(res, count)
- add the event value (
- After processing all events, return
res.
Complexity
- Time complexity:
O(n log n) - Space complexity:
O(n)
Things to watch for
Using the Wrong Comparison for Room Reuse
When checking if a room can be reused, the condition should be earliest_end_time <= current_start, not <. A meeting ending at time t allows a room to be reused by a meeting starting at time t.
Forgetting to Sort Meetings Before Processing
The min heap and two pointer approaches only work correctly when meetings are sorted by start time. Without sorting, you cannot determine the correct order of room allocation.
Returning the Max Heap Size Instead of Tracking It
The heap size changes throughout processing. You need to track the maximum size the heap reaches during iteration, or simply return the final heap size if you only pop when reusing rooms.
Python code example
from typing import List
class Solution:
def minMeetingRooms(self, intervals: List[List[int]]) -> int:
time = []
for i in intervals:
time.append((i[0], 1))
time.append((i[1], -1))
time.sort(key=lambda x: (x[0], x[1]))
res = count = 0
for t in time:
count += t[1]
res = max(res, count)
return res
C++ code example
class Solution {
public:
int minMeetingRooms(vector<vector<int>>& intervals) {
vector<pair<int, int>> time;
for (const auto& i : intervals) {
time.push_back({i[0], 1});
time.push_back({i[1], -1});
}
sort(time.begin(), time.end(), [](auto& a, auto& b) {
return a.first == b.first ? a.second < b.second : a.first < b.first;
});
int res = 0, count = 0;
for (const auto& t : time) {
count += t.second;
res = max(res, count);
}
return res;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.