题目重点:基于 Netflix 技术题汇总给出的完整合并区间题面,推导排序扫描,说明端点相接是否合并与已合并结果覆盖输入的正确性。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 区间为闭区间 `[start,end]`,因此 `[1,2]` 与 `[2,3]` 共享点 2 必须合并;坐标可比较。
- 输入 start≤end,非法区间训练代码报错;结果按 start 升序。
- 仅合并有公共点的区间,不把整数坐标下 `[1,2]` 和 `[3,4]` 视为重叠;若业务把相邻整数也合并需另议。
解题路线
- 按 start、end 升序排序。维护结果末尾的合并区间 `[L,R]`;若下一段 start>R,二者不相交,开新段;否则更新 R=max(R,next.end)。
- 不变量:已处理的所有输入段恰被结果覆盖,结果两两不相交且按开始位置排序。新段若和最后一段不交,由排序可知不会与更早段相交;若与最后一段相交,扩展末端即可保持覆盖。
- 端点相同测试必须使用 `start>R` 才开新段,不能使用 `>=`。排序是主成本;若输入已按开始位置排序可直接线性扫描。
手动走一遍
`[[1,3],[2,4],[5,5],[5,7]]` 排序后先合并为 [1,4],随后 [5,5] 开新段,最后 [5,7] 与它共享点 5,得到 `[[1,4],[5,7]]`。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def merge_closed_intervals(intervals):
ordered = sorted(intervals)
merged = []
for start, end in ordered:
if start > end:
raise ValueError("interval start exceeds end")
if not merged or start > merged[-1][1]:
merged.append([start, end])
else:
merged[-1][1] = max(merged[-1][1], end)
return merged
复杂度
n 个区间排序 O(n log n),扫描 O(n),结果与排序副本空间 O(n)。若允许原地排序且修改输入,可以减少额外存储,但会改变调用者数据。
易错点与追问
容易失分的边界
- 把端点相等当成不重叠,漏合并闭区间。
- 只把 end 设为 next.end,未取 max 导致被完全包含的区间缩短覆盖。
- 未排序就只和结果最后一段比较。
- 把‘整数上相邻’与‘有公共点’混淆。
- 从汇总帖误推某位候选人该轮必考过此题。
继续深挖
- 若输入区间已排序,能否流式输出?
- 若要动态插入区间并持续合并,平衡树索引怎么维护?
- 区间有开闭端点混合时,如何比较相接?
