Find the minimum number of conference rooms needed to schedule all meetings without conflict by sweeping independently-sorted start times and end times with two pointers — whenever a new meeting begins before the earliest one ends, you need an extra room; otherwise, recycle.
Given a list of meeting intervals [[start, end], …], return the minimum number of conference rooms required so every meeting can run simultaneously with no overlap. For [[0,30],[5,10],[15,20]] the answer is 2: meetings 5–10 and 15–20 can share room B, but 0–30 must hold room A throughout.
starts[] and ends[] — because we care only about event counts, not pairing.si through every start event (we must process each meeting). ei only advances when we free a room.starts[si] < ends[ei]? No meeting has ended yet — allocate a new room. rooms++; update maxRooms.rooms--; ei++.ends[] always exposes the smallest active end, which is the only comparison we need.Both approaches are O(n log n) time (dominated by sorting) and O(n) space. The two-pointer solution is typically faster in practice because array traversal beats heap operations by a constant factor.
0, 5, 15], ends = [10, 20, 30]. Walk both with two pointers: a start event needs a room; an end event frees one.function minMeetingRooms(intervals: number[][]): number {
const n = intervals.length;
if (n === 0) return 0;
const starts = intervals.map(i => i[0]).sort((a, b) => a - b);
const ends = intervals.map(i => i[1]).sort((a, b) => a - b);
let rooms = 0;
let maxRooms = 0;
let ei = 0;
for (let si = 0; si < n; si++) {
if (starts[si] < ends[ei]) {
// A new meeting starts before the earliest-ending meeting ends:
// we cannot reuse any room, so we need a new one.
rooms++;
maxRooms = Math.max(maxRooms, rooms);
} else {
// The earliest-ending meeting has already finished by the time
// this one starts, so we recycle that room.
rooms--;
ei++;
}
}
return maxRooms;
}starts and all end times into ends, each sorted ascending. Sorting decouples the problem: we no longer need to track which meeting ends when.rooms is the current number of rooms in use, maxRooms tracks the peak, and ei is the end-pointer (always points to the smallest active end time).rooms and update maxRooms. Note we do not advance ei.rooms and advance ei to the next end event.heap.peek() ≤ start, pop and reuse the room; otherwise push the new end. The heap always holds O(rooms) entries. Same complexity but clearer pairing.starts[si] < ends[ei] condition uses strict less-than, so a meeting ending exactly when another starts does not require an extra room — that room is recycled first.| "minimum rooms / resources for intervals" | two-pointer sweep on sorted starts & ends |
| "peak concurrent intervals" | count net +1/-1 events, track max |
| "any meeting ended before this one starts?" | compare starts[si] < ends[ei] |
| "group overlapping intervals" | sort by start; sweep line on ends |
function minMeetingRooms(intervals: number[][]): number {
const starts = intervals.map(i => i[0]).sort((a, b) => a - b);
const ends = intervals.map(i => i[1]).sort((a, b) => a - b);
let rooms = 0, maxRooms = 0, ei = 0;
for (let si = 0; si < intervals.length; si++) {
if (starts[si] < ends[ei]) {
rooms++;
maxRooms = Math.max(maxRooms, rooms);
} else {
rooms--;
ei++;
}
}
return maxRooms;
}[[0,30],[5,10],[15,20]], what is the answer?starts[si] ≥ ends[ei]?