⚠️ Note: In the NeetCode problem UI, intervals are entered as [(0, 40), (5, 10), (15, 20)]
and the parameter passed to their function is an array of objects like [{start: 0, end: 40}, …].
In this solution, we instead use a simpler array format [[0, 40], [5, 10], [15, 20]]
consistently in both the input UI and code for clarity and simplicity.
We want to find the minimum number of days needed to schedule all the given meetings,
where a single day can host multiple meetings as long as their times do not overlap.
The core idea is: as we go through meetings in chronological order,
we try to reuse an existing day whenever possible. If no existing day is free
for the next meeting, we must allocate a new day in parallel.
Handling Empty Input
Before performing any operations, the algorithm first checks if the input list of intervals is empty.
If there are no intervals provided, there is nothing to schedule — meaning no days are needed.
In this case, the algorithm immediately returns 0 and exits early.
This small edge case check keeps the logic clean and efficient.
Step 1: Sort meetings by start time
We first sort all meetings by their start time. After sorting, we handle meetings
in the order they begin — from earliest start time to latest.
This ordering lets us “schedule” meetings one by one. At any point,
the “current meeting” is simply the next meeting we’re trying to place on some day.
Because we’re going in start-time order, we can always ask:
Can this meeting fit onto any existing day from earlier, or do we need a new day?
Step 2: Track active days using a MinHeap of end times
We maintain a MinHeap of meeting end times. Each entry in the heap corresponds to a day that has been allocated so far,
and the value we store for that day is the time when the last meeting scheduled on that day ends.
Therefore, the front of the heap always tells us the earliest available day among all allocated ones.
Concretely:
-
If a day currently has a meeting that ends at time
T, thenTgoes into the heap. - The smallest end time at the top of the heap is the day that will be free the soonest.
Before we start iterating, we take the first meeting (the earliest start after sorting) and add its end time to the heap. This means: we’re currently using 1 day, and that day is “busy until” that first meeting’s end time.
Step 3: For each next meeting, either reuse a day or allocate a new one
Now we walk through the remaining meetings in sorted order. For each current meeting [start, end], we do the following:
-
Check the earliest available day:
We check the front of the heap to find the smallest end time — the meeting that finishes first on some day.
This tells us: “What is the soonest any existing day becomes free?” -
If that earliest end time ≤ current meeting’s start:
That means some day finishes its last meeting before (or exactly when) this meeting begins. So we can reuse that same day for the current meeting.
Operationally:- We remove that earliest end time from the heap — this represents freeing that day.
- We then schedule the current meeting on that same day, and push this meeting’s end time into the heap as the new “busy until…” time for that day.
-
Otherwise (earliest end time > current start):
That means even the day that frees up the earliest is still busy when this meeting wants to start. In other words: no existing day is available yet.
So we must allocate a new day in parallel for this meeting. We do this by just adding this meeting’s end time as an additional entry in the heap.
Why the heap size answers the question
The heap contains one entry for each day that has been allocated so far —
regardless of whether that day is currently occupied or has become available again for reuse.
As a result, the heap size always represents the total number of distinct days ever allocated.
That number is exactly the minimum number of days required to schedule all meetings without any overlaps on the same day.