LeetCode 252. 会议室
题目描述
✅ 252. 会议室
题意分析
给定一组会议的时间区间
intervals[i] = [start_i, end_i],判断一个人能否参加全部会议。只要存在两个会议在时间上重叠,他就分身乏术,返回 false;否则返回 true。约束里的关键信号是「区间是左闭右开语义」:一个会议在
end时刻已经结束,另一个会议正好在同一时刻开始,是可以连着参加的。所以判断重叠的条件是「前一个的结束时间严格大于后一个的开始时间」,[1, 5]与[5, 8]不算冲突,[1, 5]与[4, 8]才算。另一个信号是输出只有真假两种,不需要统计冲突了几次、也不需要还原是哪两个会议冲突。这意味着一旦发现第一处冲突就能立刻收工,不必扫完全部数据。
边界包括:数组为空或只有一个会议,此时不存在「两个会议」,应返回 true;两个会议端点相接;输入完全无序,甚至可能出现开始时间相同的会议。
解法:按开始时间排序后检查相邻区间
核心思路
将会议按开始时间升序排列后,时间轴顺序就确定了。若当前会议的开始时间早于前一个会议的结束时间,两场会议重叠,无法全部参加;否则继续检查。
不排序时只能拿每两场会议逐对比较,最坏需要 $O(n^2)$。排序的价值是把时间上最接近的会议放到一起,让全局冲突能够在一次线性扫描中暴露出来。
为什么只看相邻会议:排序后,一旦某个更早的会议延伸到当前会议,它在经过中间会议时就已经产生过相邻重叠并被发现。因此所有相邻区间均不重叠,就能推出任意两场会议都不重叠。
区间按半开语义理解:前一场在
t结束、后一场在t开始可以无缝衔接,所以冲突条件是currentStart < previousEnd,不是<=。扫描不变量是:检查第
i场之前,前i场会议已经确认互不重叠。当前场只要不与紧邻的前一场冲突,就能安全加入这段时间线;否则立即返回,无需继续比较。
解题步骤
- 按每个区间的开始时间升序排序。
- 从第二个会议开始扫描。
- 若
intervals[i][0] < intervals[i - 1][1],立即返回false。- 扫描结束仍未发现重叠,返回
true。例如
[[0,30],[5,10],[15,20]]排序后,第二场开始时间 5 小于前一场结束时间 30,直接判定冲突;[[7,10],[10,12]]则允许首尾相接。
代码实现
import java.util.Arrays;
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;
}
}
import "sort"
func canAttendMeetings(intervals [][]int) bool {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][0] < intervals[j][0]
})
for i := 1; i < len(intervals); i++ {
if intervals[i][0] < intervals[i-1][1] {
return false
}
}
return true
}
复杂度分析
- 时间复杂度:$O(n \log n)$,排序占主导,扫描为 $O(n)$。
- 空间复杂度:取决于排序实现;Java 对对象数组排序最坏使用 $O(n)$ 辅助空间,Go 排序栈为 $O(\log n)$。算法本身只使用常数个变量。
关键点总结
- 排序把任意区间的冲突问题转成相邻区间检查。
- 结束时间等于下一场开始时间不算重叠。
- 发现第一处冲突即可提前返回。
- 当前实现会改变
intervals的顺序,这是原地排序的正常结果。
易错点总结
- 冲突条件写成
<=,会把[1,2]与[2,3]误判为重叠。- 按结束时间排序后仍机械地比较相邻区间,论证会改变;本解法必须按开始时间排序。
- 只比较排序前的相邻会议,会漏掉原数组中不相邻但时间重叠的区间。
- 比较器写成
a[0] - b[0]可能整数溢出,应使用Integer.compare。
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 253. 会议室 II | 中等 | 求最少会议室数量 |
| 56. 合并区间 | 中等 | 排序后合并重叠区间 |
| 57. 插入区间 | 中等 | 有序区间中插入并合并 |
| 435. 无重叠区间 | 中等 | 按结束时间贪心删最少区间 |
| 986. 区间列表的交集 | 中等 | 双指针求两组区间交集 |
| 1229. 安排会议日程 | 中等 | 双指针找满足时长的空档 |
| 759. 员工空闲时间 | 困难 | 多人日程求公共空闲区间 |