SDE / Applied Scientist · OA / Coding

Amazon Coding:合并区间,端点相接究竟算不算重叠?

先固定闭区间语义,再用排序扫描维持覆盖不变量;与会议室半开区间的边界区别。

题目重点:先固定闭区间语义,再用排序扫描维持覆盖不变量;与会议室半开区间的边界区别。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 输入闭区间[start,end],start≤end,坐标可为实数,端点相接合并。
  • 输出最大连通覆盖区间,不做会议室占用计数;题目额外贪心/扫描线规则、附件样例待核。

解题路线

  1. 按start排序,维护已完成结果与最后活动区间。新start≤活动end时相交,扩end到max;否则活动区间不会再被后续start连接,可以定稿。
  2. 排序后未来start不小于当前start,保证间隔出现后过去区间安全完成。嵌套区间不能把end直接设成新end,必须取max。
  3. 闭区间[1,2]/[2,3]相交;半开会议区间[1,2)/[2,3)不重叠,可以分开,但若目标只是半开集合的连续表示也可合并。判据必须根据输出定义而非背固定<=。
  4. 若按扫描线处理闭区间事件,同坐标start/end的处理顺序影响相交判断,不能直接套半开会议计数。本文排序扫描不需要构造所有点事件。
  5. 输入已排序则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缩小。
  • 混同会议室数量。
  • 扫描线同坐标事件顺序不一致。

继续深挖

  • 半开区间与空区间如何处理?
  • 在线新增区间怎样找到所有受影响邻居?
  • 输出覆盖总长度或最大重叠数怎么换状态?
✓已复制微信号!