Meeting Rooms II

Meeting Rooms II is the question that separates people who memorize from people who think. Meeting Rooms only asked yes or no. This one asks how many rooms you need so no meeting clashes. The answer is the largest number of meetings happening at the same time. Finding that peak is the real puzzle.

🎯 The Problem

You get a list of meetings and find the fewest rooms needed.

  • Each meeting is a pair: a start time and an end time.
  • Find the smallest number of rooms so no two meetings clash.
  • Two meetings clash when both are running at the same instant.
  • The answer is the peak overlap: the most meetings live at one moment.
  • A meeting ending at 10 and another starting at 10 can share one room.
Input: intervals = [[0, 30], [5, 10], [15, 20]]
Output: 2
Explanation: At time 5, the meetings [0, 30] and [5, 10] are both live.
That is two at once, so two rooms are enough for the whole day.

Here is the input drawn on a number line. Around time 5 to 10, two meetings run together, and that is the peak.

0--------30

5-10

15-20

at time 5: A and B both live = 2 rooms

at time 15: A and C both live = still 2

🐒 Approach 1: Count At Every Time Point (Brute Force)

Walk the clock and count live meetings at each tick.

The idea:

  • Step over every time point on the clock.
  • At each point, count how many meetings are live.
  • The largest count you see is the answer.

Why it is weak:

  • The clock can be huge. Times may go up to a million.
  • For each tick you scan all meetings.
  • The cost depends on how big the numbers are, not just the meeting count.

Here is the sweep-every-time-point code:

meeting_rooms_ii_time_points.py
def min_meeting_rooms(intervals):
if not intervals:
return 0
first = min(start for start, end in intervals)
last = max(end for start, end in intervals)
best = 0
for time in range(first, last + 1):
active = sum(start <= time < end for start, end in intervals)
best = max(best, active)
return best

⚑ Approach 2: Min-Heap Of End Times (Better)

The idea in one line: keep the rooms in use as a min-heap of their end times.

The idea:

  • Sort the meetings by start time.
  • A min-heap always hands you the smallest value fast.
  • Here the smallest value is the room that frees up soonest.

How it works:

  • For each meeting, look at the heap top, the earliest end.
  • If that end is at or before this start, that room is free, so pop it.
  • Push this meeting’s end, because it takes a room.
  • The heap size right now is the rooms in use. Track its peak.

Why it is fast:

  • Sorting is O(n log n). Each heap push and pop is O(log n).
  • Done n times, the total stays O(n log n).

Here is the min-heap code for that idea:

meeting_rooms_ii_heap.py
import heapq
def min_meeting_rooms(intervals):
intervals.sort()
rooms = []
for start, end in intervals:
if rooms and rooms[0] <= start:
heapq.heappop(rooms)
heapq.heappush(rooms, end)
return len(rooms)

⚑ Approach 3: Split Starts And Ends (Best)

The idea in one line: sort starts and ends apart, then sweep both with two pointers and no heap.

The idea:

  • Take all start times into one list and all end times into another.
  • Sort both lists.
  • Sweep through time with two pointers.

How it works:

  • Walk the starts in order. Compare each start with the smallest end not yet passed.
  • If the start is before that end, a new meeting begins while an old one runs, so add a room and track the peak.
  • If the start is at or after that end, an old meeting freed a room first, so reuse it and move the end pointer forward.

Why it is fast:

  • Two sorts cost O(n log n). The sweep is O(n).
  • No heap structure to maintain.

Here is the heap version as a flow.

yes, room frees

no, all busy

Sort meetings by start

Take next meeting

Is earliest end at or before this start?

Pop that end from heap

Keep heap as is

Push this meeting end, track heap size

Steps to Solve

  1. Sort the meetings by start time.
  2. Make an empty min-heap that will hold end times.
  3. For each meeting, if the smallest end in the heap is at or before this start, pop it, because that room is free.
  4. Push this meeting’s end onto the heap.
  5. The current heap size is the rooms in use. Track the largest size you see.
  6. Return that largest size.

This Python version uses heapq, the built-in min-heap, to track end times.

meeting_rooms_ii.py
import heapq
def min_meeting_rooms(intervals):
intervals.sort(key=lambda block: block[0]) # sort by start
heap = [] # min-heap of end times
rooms = 0
for start, end in intervals:
if heap and heap[0] <= start: # earliest room is free
heapq.heappop(heap)
heapq.heappush(heap, end) # this meeting takes a room
rooms = max(rooms, len(heap)) # track the peak
return rooms
intervals = [[0, 30], [5, 10], [15, 20]]
print(min_meeting_rooms(intervals))

The output of the above code will be:

2

Now let us walk through the Python heap version line by line and see why each part is written this way.

def min_meeting_rooms(intervals):
intervals.sort(key=lambda block: block[0])
heap = []
rooms = 0

We sort by start so we meet the meetings in time order. The heap will hold the end times of meetings that are currently using a room. rooms will remember the most rooms we ever needed at once.

for start, end in intervals:
if heap and heap[0] <= start:
heapq.heappop(heap)

For each meeting we look at heap[0], which in a min-heap is always the smallest end time, the room that frees up soonest. The check heap[0] <= start reads as β€œthat room is already free by the time this meeting starts.” So we pop it, because we can reuse that room. We use <= because a meeting ending exactly at this start has already finished.

heapq.heappush(heap, end)
rooms = max(rooms, len(heap))
return rooms

Every meeting needs a room, so we always push its end onto the heap. We did the pop first so a freed room gets reused instead of adding a new one. The heap size right now is the number of rooms in use, so we update rooms with the peak. At the end rooms holds the most rooms ever needed, which is the answer.

⏱️ Time and Space Complexity

The brute force over every time point depends on how large the times are, so it can be very slow. The heap version sorts in O(n log n) and does n heap operations each O(log n), so the total is O(n log n). The split-events version sorts two lists in O(n log n) then sweeps in O(n), so it is also O(n log n). Both use O(n) extra space for the heap or the event lists. The deep idea is that the answer is the peak overlap, the most meetings live at once.

Approach Time Complexity Space Complexity
Brute force over every time point O(n Γ— maxTime) O(1)
Min-heap of end times O(n log n) O(n)
Split starts and ends, two pointers O(n log n) O(n)

Tip

The answer is never about the total meetings. It is the largest number happening at the same instant. Both the heap and the split-events sweep are just clean ways to find that peak.

🧩 Key Takeaways

  • βœ… The answer is the peak overlap, the most meetings live at the same time.
  • βœ… Sort by start so you meet the meetings in time order.
  • βœ… A min-heap of end times tells you the room that frees up soonest.
  • βœ… Reuse a room when its end is at or before the next start.
  • βœ… The heap size at its largest is the number of rooms you need.

Check Your Knowledge

4 questions Show quiz Hide quiz

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does Meeting Rooms II ask you to return?

    Why: It asks for the fewest rooms needed, which equals the most meetings happening at the same instant.

  2. 2

    In the heap solution, what does the top of the min-heap represent?

    Why: A min-heap keeps the smallest end on top, which is the room that becomes free the soonest.

  3. 3

    When can we reuse a room for the next meeting?

    Why: If the soonest-ending room finishes by the time the next meeting starts, that room is free to reuse.

  4. 4

    What is the time complexity of the min-heap solution?

    Why: Sorting is O(n log n) and each of the n heap operations is O(log n), so the total is O(n log n).

πŸš€ What’s Next?