We need to figure out the maximum number of meetings that overlap at any point in time. That peak overlap count equals the minimum number of rooms required, because at that moment, every one of those overlapping meetings needs its own room.
A hotel makes the idea concrete. Guests check in and check out at different times, and the number of rooms you need depends on the busiest moment, when the most guests are checked in at once. Two guests whose stays overlap cannot share a room.
A meeting room becomes free the moment a meeting ends. If a new meeting starts at or after the end time of an existing meeting, it can reuse that room. So the task reduces to tracking which rooms are free and when.
1 <= intervals.length <= 10^4 → With n up to 10,000, an O(n^2) brute force runs up to 100 million operations, which is borderline. O(n log n) is comfortable, so that is the target.0 <= start_i < end_i <= 10^6 → A meeting always has positive duration since start_i < end_i, so a meeting never overlaps with itself. Time values reach one million, which rules out indexing an array by timestamp unless that array is bounded carefully. The event-based approaches below avoid the timestamp range entirely.The peak number of concurrent meetings always occurs at some meeting's start time. A new overlap can only begin when a meeting starts, so checking the overlap count at every start time captures the maximum. For each meeting, count how many meetings are active at the instant it starts. The largest count over all meetings is the answer.
A meeting j is active at time t when intervals[j][0] <= t and intervals[j][1] > t. The end is strict because a meeting that ends exactly at t has already freed its room.
maxRooms = 0.i, count how many meetings are active at time intervals[i][0] (the start of meeting i).j is active at time t if intervals[j][0] <= t and intervals[j][1] > t.maxRooms with the maximum count found.maxRooms.Loading animation...
Recounting overlaps from scratch for each meeting wastes work. Processing meetings in chronological order lets us maintain the room count incrementally instead.
Sorting meetings by start time and processing them one by one simulates room allocation in real time. Maintain a min-heap that stores the end times of all ongoing meetings. The heap's minimum is the time the next room becomes free.
When a new meeting arrives, compare its start time against the heap's minimum. If the earliest-ending meeting finishes before or exactly when the new meeting starts, pop it: that room is reused. Otherwise the new meeting needs a fresh room. In both cases, push the new meeting's end time onto the heap.
The heap size always equals the number of rooms in use, and since the algorithm never shrinks the heap below the current concurrency, the maximum heap size reached is the answer. With the loop as written, every meeting pushes exactly once and pops at most once, so the final heap size is the peak concurrency.
Processing meetings in start-time order means the room a meeting reuses, if any, is always the one that frees up earliest. Checking only the heap minimum is enough: if the earliest-ending meeting has not finished by the new meeting's start, no other ongoing meeting has finished either, so a new room is required. If it has finished, reusing it is always safe because all rooms are interchangeable and holding it back for a later meeting can never reduce the total.
Loading animation...
The heap tracks which room frees up, but the answer only depends on how many rooms are free at each moment, not which one. Dropping that bookkeeping leads to a heap-free solution that tracks start and end events separately.
Each meeting splits into two events: a start (a room is needed) and an end (a room is freed). Laid out in chronological order, these events let us walk through time and track the room count.
Separate all start times into one array and all end times into another, then sort both. Two pointers sweep through them. Each start that occurs before the next end forces another room. Each time a start meets an end that has already passed, a room is reused. No heap is required, only two sorted arrays and two pointers.
Counting rooms depends only on the order of events, not on which specific meeting ends. Separating starts from ends discards the pairing between them, but the room count at any moment is the number of meetings started minus the number ended, and that difference does not care about identity. If 3 meetings have started and 1 has ended, 2 rooms are in use regardless of which meeting ended. Sorting starts and ends independently and sweeping with two pointers increments on each start and advances past an end whenever one has already occurred, so rooms records the peak of that running difference.
startPtr = 0 and endPtr = 0, and a counter rooms = 0.startPtr < n:starts[startPtr] < ends[endPtr], we need a new room (increment rooms). Otherwise, we reuse a room (increment endPtr). Always increment startPtr.rooms.Loading animation...