Problem Overview: Can One Person Attend All Meetings?
LeetCode 252 Meeting Rooms gives you an array of meeting time intervals where each interval is represented as [start, end]. Your task is to determine whether a single person can attend every meeting — meaning no two meetings overlap in time. If any two meetings conflict, return false; if all meetings are compatible, return true.
An overlap between two intervals [a, b] and [c, d] occurs when one starts before the other ends: specifically when max(a, c) < min(b, d). Two meetings that share only an endpoint — where one ends exactly when the other starts — are not considered overlapping in this problem. A person can leave one meeting and immediately enter the next.
The problem is marked easy and is considered foundational in the interval scheduling family. It serves as the stepping stone toward Meeting Rooms II (LeetCode 253), which asks for the minimum number of rooms required rather than a simple yes-or-no answer.
- Input: intervals where intervals[i] = [start_i, end_i], 0 <= start_i < end_i <= 10^6
- Output: true if a person can attend all meetings (no overlaps), false otherwise
- Intervals can be given in any order — sorting is your responsibility
- Empty array or single interval always returns true
- Two meetings sharing an endpoint [1,5],[5,10] are NOT overlapping
- Constraints: 0 <= intervals.length <= 10^4
The Sorting Insight: From O(n²) to O(n)
The brute-force approach compares every pair of intervals to check for overlap. With n intervals there are n*(n-1)/2 pairs, giving O(n²) time complexity. For the constraint of up to 10,000 intervals this is 50 million comparisons — technically acceptable but needlessly slow.
The key insight is that after sorting intervals by start time, you only need to check consecutive pairs. If interval A starts before interval B (A.start <= B.start after sorting), the only way A and B overlap is if A has not yet ended when B begins — i.e., if B.start < A.end. You never need to compare non-adjacent intervals because any overlap between distant intervals would already be caught by an adjacent pair.
Sorting takes O(n log n) time. The subsequent scan through consecutive pairs takes O(n) time. The total complexity is O(n log n), dominated by the sort. This is optimal for comparison-based sorting and far better than the brute-force O(n²) approach.
Sort Reduces Overlap Check from O(n²) to O(n)
Sorting by start time reduces the overlap check from O(n²) all-pairs comparisons to O(n) consecutive-pair comparisons. After sorting, if intervals[i] and intervals[j] overlap for some i < j, then intervals[i] and intervals[i+1] must also overlap — so catching adjacent conflicts is sufficient. You never need to look further than the next interval in the sorted order.
Overlap Detection: Single Pass After Sorting
Once the intervals are sorted by start time, the overlap check is a single forward pass. Iterate from index 1 to n-1. At each index i, compare intervals[i][0] (the start of the current meeting) with intervals[i-1][1] (the end of the previous meeting). If the current meeting starts strictly before the previous meeting ends, the two overlap and you return false immediately.
If you complete the entire pass without finding any overlap, you return true — the person can attend all meetings. The check at each step is a single integer comparison, making the loop O(n) after the sort. No additional data structures are needed beyond the sorted array itself.
The condition for an overlap is: intervals[i][0] < intervals[i-1][1]. Note the strict less-than: if intervals[i][0] == intervals[i-1][1], the meetings share only an endpoint and do not overlap. A meeting that starts exactly when the previous one ends is allowed.
- 1Sort intervals by start time: intervals.sort(key=lambda x: x[0])
- 2Loop i from 1 to len(intervals) - 1
- 3If intervals[i][0] < intervals[i-1][1]: return False (overlap detected)
- 4After the loop ends with no overlap found: return True
- 5Special cases: empty array or single interval — return True immediately
Why Sort by Start Time Works
Sorting by start time creates a natural ordering where each interval begins at or after the previous interval begins. In this ordered sequence, the only way interval i can conflict with any earlier interval j (j < i) is through interval i-1. If interval i starts before interval i-1 ends, the overlap is caught directly. If interval i starts after interval i-1 ends, it necessarily starts after all earlier intervals end too — because they all end no later than interval i-1 does after sorting.
This argument holds because sorting by start guarantees that among all intervals that start before interval i, interval i-1 has the latest end time among those whose start time is immediately before i. Wait — actually the argument is simpler: after sorting by start, interval i-1 has the largest end time among all intervals at or before position i-1 that could possibly conflict with i, because any interval j with j < i-1 that has a later end time would have been caught by a conflict with an interval between j and i.
An alternative approach is to sort by end time instead of start time. Sorting by end time also reduces the problem to consecutive comparisons and gives the same result. The condition changes slightly but the overall logic remains equivalent. Sorting by start time is the more common and intuitive approach in interviews.
Sorting by End Time Also Works
Sorting by end time also works for this problem and gives the same O(n log n) time complexity. When sorted by end time, check if intervals[i][0] < intervals[i-1][1] — the same condition. Both orderings reduce overlap detection to adjacent comparisons. Sorting by start time is more intuitive since the problem describes intervals by [start, end] and matching rooms greedily by earliest start is the natural mental model.
Edge Cases: Empty List, Single Meeting, Shared Endpoints
An empty intervals array means there are no meetings at all, so the person trivially attends all zero meetings. Return true without entering any loop. In Python and Java, the for/while loop simply does not execute when the array is empty. No explicit early return is needed, but adding one improves readability.
A single meeting interval also returns true immediately — one meeting never conflicts with itself. The loop starts at index 1 and since there is no index 1, it does not execute. Return true. This case requires no special handling beyond what the general algorithm already does.
Meetings that share an endpoint, such as [1, 5] and [5, 10], are not overlapping. The overlap condition uses strict less-than: intervals[i][0] < intervals[i-1][1]. When intervals[i][0] == intervals[i-1][1], the condition is false and no overlap is reported. A zero-length meeting [3, 3] is not a valid input according to the constraint start < end, but if it were, it would behave correctly since 3 < 3 is false.
- 1Empty array []: return True immediately — zero meetings, no conflicts possible
- 2Single interval [[a, b]]: return True — one meeting cannot conflict with itself
- 3Adjacent endpoint [1,5],[5,10]: intervals[1][0]=5 is NOT < intervals[0][1]=5, so no overlap
- 4Exact duplicate [1,5],[1,5]: intervals[1][0]=1 < intervals[0][1]=5 — overlap detected, return False
- 5Already-sorted input: sort is still O(n log n) but most implementations handle this efficiently
Code Walkthrough: Python and Java
In Python, the full solution is four lines. Sort with intervals.sort(key=lambda i: i[0]). Then loop: for i in range(1, len(intervals)): if intervals[i][0] < intervals[i-1][1]: return False. Return True after the loop. Time complexity is O(n log n) for the sort; the scan is O(n). Space complexity is O(1) extra if sorting is done in-place, which Python's built-in sort does (Timsort modifies the list in place).
In Java, Arrays.sort(intervals, (a, b) -> a[0] - b[0]) sorts the 2D array by the first element. Then a for loop from i = 1 to intervals.length - 1 checks if intervals[i][0] < intervals[i-1][1], returning false if so. Return true after the loop. Java's Arrays.sort uses a dual-pivot quicksort for primitives and a merge sort variant for objects — both are O(n log n) average.
Both implementations have identical algorithmic structure: sort by start, scan consecutive pairs, return false on first overlap, return true if none found. The only language differences are syntax for lambda comparators and array indexing. Interview candidates should be comfortable writing both without hesitation.
Use < Not <=: Shared Endpoints Are Not Overlapping
Use strict less-than (<) not less-than-or-equal (<=) when checking for overlap. Meetings [1,5] and [5,10] do NOT overlap — the first ends exactly when the second begins, so the person can attend both back-to-back. Using <= would incorrectly flag this as an overlap and return false when the correct answer is true. The overlap condition is: current.start < previous.end, not current.start <= previous.end.