Approach Summary
Sort intervals by start time. Check each consecutive pair — if any start < previous end, return false.
Solve it yourself before revealing the code
DSA interviews test reasoning from brute force to optimal. Think through the constraints first.
Solution Progression (Brute Force → Most Optimized)
Understand the architectural evolution from naive baseline to optimal complexity.
| Approach | Time | Space | Core Strategy / Trade-off |
|---|---|---|---|
| 1 Approach 1: Sorting and Consecutive Interval Overlap Check (Optimal) | O(n log n) | O(1) | Sort by start time and verify that every meeting starts at or after the previous meeting ends. |
| 2 Approach 2: Pairwise Conflict Check (Baseline) | O(n²) | O(1) | Checks every pair of intervals (i, j) for temporal overlap in O(n²) time without sorting. |
| 3 Approach 2: Pairwise Conflict Check (Baseline) | O(n²) | O(1) | Checks every pair of intervals (i, j) for temporal overlap in O(n²) time without sorting. |
Approach 1: Sorting and Consecutive Interval Overlap Check (Optimal)
After sorting by start time, any possible scheduling conflict must happen between adjacent meetings. If intervals[i][0] < intervals[i - 1][1], return false. If no conflict is found, return true.
Approach 1: Sorting and Consecutive Interval Overlap Check (Optimal) Implementation
Approach 1: Sorting and Consecutive Interval Overlap Check (Optimal)
public class Solution {
public boolean canAttendMeetings(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] < intervals[i - 1][1]) return false;
}
return true;
}
}class Solution {
public:
bool canAttendMeetings(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
for (int i = 1; i < intervals.size(); i++) {
if (intervals[i][0] < intervals[i - 1][1]) return false;
}
return true;
}
};class Solution:
def canAttendMeetings(self, intervals: list[list[int]]) -> bool:
intervals.sort(key=lambda x: x[0])
for i in range(1, len(intervals)):
if intervals[i][0] < intervals[i - 1][1]:
return False
return Truefunction canAttendMeetings(intervals) {
intervals.sort((a, b) => a[0] - b[0]);
for (let i = 1; i < intervals.length; i++) {
if (intervals[i][0] < intervals[i - 1][1]) return false;
}
return true;
} Approach 2: Pairwise Conflict Check (Baseline)
For every distinct pair of meetings i and j, verifies whether their time intervals intersect: max(start_i, start_j) < min(end_i, end_j). If any overlap is found, returns false immediately.
Approach 2: Pairwise Conflict Check (Baseline) Implementation
Approach 2: Pairwise Conflict Check (Baseline)
class Solution {
public boolean canAttendMeetings(int[][] intervals) {
for (int i = 0; i < intervals.length; i++) {
for (int j = i + 1; j < intervals.length; j++) {
if (Math.max(intervals[i][0], intervals[j][0]) < Math.min(intervals[i][1], intervals[j][1])) {
return false;
}
}
}
return true;
}
}class Solution {
public:
bool canAttendMeetings(vector<vector<int>>& intervals) {
for (int i = 0; i < intervals.size(); i++) {
for (int j = i + 1; j < intervals.size(); j++) {
if (max(intervals[i][0], intervals[j][0]) < min(intervals[i][1], intervals[j][1])) {
return false;
}
}
}
return true;
}
};class Solution:
def canAttendMeetings(self, intervals: list[list[int]]) -> bool:
n = len(intervals)
for i in range(n):
for j in range(i + 1, n):
if max(intervals[i][0], intervals[j][0]) < min(intervals[i][1], intervals[j][1]):
return False
return Truefunction canAttendMeetings(intervals) {
const n = intervals.length;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
if (Math.max(intervals[i][0], intervals[j][0]) < Math.min(intervals[i][1], intervals[j][1])) {
return false;
}
}
}
return true;
} Approach 2: Pairwise Conflict Check (Baseline)
For every distinct pair of meetings i and j, verifies whether their time intervals intersect: max(start_i, start_j) < min(end_i, end_j). If any overlap is found, returns false immediately.
Approach 2: Pairwise Conflict Check (Baseline) Implementation
Approach 2: Pairwise Conflict Check (Baseline)
class Solution {
public boolean canAttendMeetings(int[][] intervals) {
for (int i = 0; i < intervals.length; i++) {
for (int j = i + 1; j < intervals.length; j++) {
if (Math.max(intervals[i][0], intervals[j][0]) < Math.min(intervals[i][1], intervals[j][1])) {
return false;
}
}
}
return true;
}
}class Solution {
public:
bool canAttendMeetings(vector<vector<int>>& intervals) {
for (int i = 0; i < intervals.size(); i++) {
for (int j = i + 1; j < intervals.size(); j++) {
if (max(intervals[i][0], intervals[j][0]) < min(intervals[i][1], intervals[j][1])) {
return false;
}
}
}
return true;
}
};class Solution:
def canAttendMeetings(self, intervals: list[list[int]]) -> bool:
n = len(intervals)
for i in range(n):
for j in range(i + 1, n):
if max(intervals[i][0], intervals[j][0]) < min(intervals[i][1], intervals[j][1]):
return False
return Truefunction canAttendMeetings(intervals) {
const n = intervals.length;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
if (Math.max(intervals[i][0], intervals[j][0]) < Math.min(intervals[i][1], intervals[j][1])) {
return false;
}
}
}
return true;
} Edge Cases to Watch
- Empty intervals or single meeting (always returns true)
- Meetings touching at exact boundary (e.g. [7, 10] and [10, 15]; valid, returns true)
- Multiple meetings overlapping with the first (returns false)
Master the Intervals Pattern
Study the core invariant, step-by-step decision framework, and common interview traps for the Intervals pattern.
How to Recognize This Pattern
- "Can one person attend all meetings"
- Sort + single overlap check
Complexity Analysis
Time Complexity
O(n log n)
Space Complexity
O(1)