题目重点:先固定闭区间语义,再用排序扫描维持覆盖不变量;与会议室半开区间的边界区别。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 输入闭区间[start,end],start≤end,坐标可为实数,端点相接合并。
- 输出最大连通覆盖区间,不做会议室占用计数;题目额外贪心/扫描线规则、附件样例待核。
解题路线
- 按start排序,维护已完成结果与最后活动区间。新start≤活动end时相交,扩end到max;否则活动区间不会再被后续start连接,可以定稿。
- 排序后未来start不小于当前start,保证间隔出现后过去区间安全完成。嵌套区间不能把end直接设成新end,必须取max。
- 闭区间[1,2]/[2,3]相交;半开会议区间[1,2)/[2,3)不重叠,可以分开,但若目标只是半开集合的连续表示也可合并。判据必须根据输出定义而非背固定<=。
- 若按扫描线处理闭区间事件,同坐标start/end的处理顺序影响相交判断,不能直接套半开会议计数。本文排序扫描不需要构造所有点事件。
- 输入已排序则O(n)扫描;大量在线插入可能用有序map定位邻居,不能每次遍历全部仍声称对数更新。
手动走一遍
[1,5],[2,3],[5,8],[10,10]输出[1,8],[10,10];[10,10]是非空闭区间。10,000组输入用区间相交图的连通分量独立求并集外界,对照通过。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def merge_intervals(intervals):
"""Closed real intervals [start, end]; touching endpoints merge."""
pairs = list(intervals)
if any(start > end for start, end in pairs):
raise ValueError("inverted interval")
result = []
for start, end in sorted(pairs):
if result and start <= result[-1][1]:
result[-1][1] = max(result[-1][1], end)
else:
result.append([start, end])
return result
复杂度
O(n log n)排序+O(n)扫描;复制输入和结果O(n)空间,未原地改用户列表。已排序输入可以流式输出已封口区间。
易错点与追问
容易失分的边界
- 端点相接没定义。
- 嵌套把end缩小。
- 混同会议室数量。
- 扫描线同坐标事件顺序不一致。
继续深挖
- 半开区间与空区间如何处理?
- 在线新增区间怎样找到所有受影响邻居?
- 输出覆盖总长度或最大重叠数怎么换状态?
