🧠
Sorting + Two Pointers (Sweep Line with Separate Start and End Arrays)
💡 This approach introduces sorting and two-pointer technique to efficiently count overlaps by processing start and end times separately.
Intuition
Sort all start times and end times. Use two pointers to track how many meetings are ongoing by comparing next start and end times.
Algorithm
- Extract and sort all start times and end times separately.
- Initialize two pointers for start and end arrays.
- Iterate through start times; if a meeting starts before the earliest ending meeting ends, increment room count.
- Otherwise, move the end pointer forward to free a room.
- Track the maximum number of rooms needed during iteration.
💡 This approach cleverly uses sorted arrays and pointers to simulate meeting overlaps without nested loops.
def minMeetingRooms(intervals):
starts = sorted(i[0] for i in intervals)
ends = sorted(i[1] for i in intervals)
s_ptr = e_ptr = 0
used_rooms = 0
max_rooms = 0
while s_ptr < len(intervals):
if starts[s_ptr] < ends[e_ptr]:
used_rooms += 1
s_ptr += 1
else:
used_rooms -= 1
e_ptr += 1
max_rooms = max(max_rooms, used_rooms)
return max_rooms
# Driver code
intervals = [[0,30],[5,10],[15,20]]
print(minMeetingRooms(intervals)) # Output: 2
Line Notes
starts = sorted(i[0] for i in intervals)Sort all meeting start times to process in chronological order.
ends = sorted(i[1] for i in intervals)Sort all meeting end times to know when rooms free up.
if starts[s_ptr] < ends[e_ptr]:If next meeting starts before earliest meeting ends, need a new room.
used_rooms -= 1If a meeting ended before next starts, free a room by moving end pointer.
import java.util.*;
public class Solution {
public static int minMeetingRooms(int[][] intervals) {
int n = intervals.length;
int[] starts = new int[n];
int[] ends = new int[n];
for (int i = 0; i < n; i++) {
starts[i] = intervals[i][0];
ends[i] = intervals[i][1];
}
Arrays.sort(starts);
Arrays.sort(ends);
int s_ptr = 0, e_ptr = 0, usedRooms = 0, maxRooms = 0;
while (s_ptr < n) {
if (starts[s_ptr] < ends[e_ptr]) {
usedRooms++;
s_ptr++;
} else {
usedRooms--;
e_ptr++;
}
maxRooms = Math.max(maxRooms, usedRooms);
}
return maxRooms;
}
public static void main(String[] args) {
int[][] intervals = {{0,30},{5,10},{15,20}};
System.out.println(minMeetingRooms(intervals)); // Output: 2
}
}
Line Notes
int[] starts = new int[n];Create array to hold all start times separately.
Arrays.sort(starts);Sort start times to process meetings in chronological order.
if (starts[s_ptr] < ends[e_ptr]) {Check if next meeting starts before earliest meeting ends to allocate room.
usedRooms--Free a room when a meeting ends before next starts by moving end pointer.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int minMeetingRooms(vector<vector<int>>& intervals) {
int n = intervals.size();
vector<int> starts(n), ends(n);
for (int i = 0; i < n; i++) {
starts[i] = intervals[i][0];
ends[i] = intervals[i][1];
}
sort(starts.begin(), starts.end());
sort(ends.begin(), ends.end());
int s_ptr = 0, e_ptr = 0, usedRooms = 0, maxRooms = 0;
while (s_ptr < n) {
if (starts[s_ptr] < ends[e_ptr]) {
usedRooms++;
s_ptr++;
} else {
usedRooms--;
e_ptr++;
}
maxRooms = max(maxRooms, usedRooms);
}
return maxRooms;
}
int main() {
vector<vector<int>> intervals = {{0,30},{5,10},{15,20}};
cout << minMeetingRooms(intervals) << endl; // Output: 2
return 0;
}
Line Notes
vector<int> starts(n), ends(n);Separate arrays for start and end times to process events.
sort(starts.begin(), starts.end());Sort start times to simulate meeting start events in order.
if (starts[s_ptr] < ends[e_ptr]) {If next meeting starts before earliest ends, allocate a room.
usedRooms--Free a room when a meeting ends before next starts by advancing end pointer.
function minMeetingRooms(intervals) {
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 s_ptr = 0, e_ptr = 0, usedRooms = 0, maxRooms = 0;
while (s_ptr < intervals.length) {
if (starts[s_ptr] < ends[e_ptr]) {
usedRooms++;
s_ptr++;
} else {
usedRooms--;
e_ptr++;
}
maxRooms = Math.max(maxRooms, usedRooms);
}
return maxRooms;
}
// Test
console.log(minMeetingRooms([[0,30],[5,10],[15,20]])); // Output: 2
Line Notes
const starts = intervals.map(i => i[0]).sort((a,b) => a - b);Extract and sort start times to process chronologically.
if (starts[s_ptr] < ends[e_ptr]) {Compare next start with earliest end to decide if new room needed.
usedRooms--Free a room when a meeting ends before next starts by moving end pointer.
maxRooms = Math.max(maxRooms, usedRooms);Track maximum concurrent meetings to find minimum rooms.
Sorting start and end arrays takes O(n log n), and the two-pointer sweep is O(n).
💡 For n=20, sorting takes about 20*log2(20) ≈ 86 operations, much faster than brute force.
Interview Verdict: Accepted and efficient for large inputs; a common interview solution.
This approach balances clarity and efficiency, making it a strong candidate solution.