SWE · Coding

TikTok Merge Intervals:排序扫描、嵌套区间与端点语义

闭区间相接合并,维护已处理并集,处理嵌套、重复、点区间并避免修改输入。

题目重点:闭区间相接合并,维护已处理并集,处理嵌套、重复、点区间并避免修改输入。

题意与假设

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

  • 训练为闭区间[start,end],start≤end;[1,2]与[2,3]共享点2,合并为[1,3]。
  • 允许重复、负端点、零长度点区间;空输入返回空列表,不修改输入。
  • 不按整数相邻规则合并[1,2]与[3,4];端点所在数轴连续,gap仍存在。

解题路线

  1. 按start再end排序。输出维护已扫描区间的并集,以起点递增且互不相交的区间表示;后来的起点不会回到此前输出区间的左侧。
  2. 若当前start≤最后输出end,二者重叠,最后区间右端改为max(旧end,当前end)。使用max才能处理包含关系:较短内层区间不能让已合并范围缩小。
  3. 若start>最后end,中间存在未覆盖间隙,最后输出已经定型,将当前区间作为新段加入。后续起点更大,不会再填回这个间隙,所以无需回看更早段。
  4. 正确性按扫描归纳:重叠时并集正是同一起点到更大右端;分离时追加保留全部覆盖且不填空隙。每次更新后输出仍按起点递增,且任意相邻段之间有严格间隙。
  5. 端点政策必须与会议室题分开。闭区间共享端点会重叠;半开区间在端点相接时不同时占用。若业务只要求覆盖并集,半开相接区间也可合成连续段,但其合并动机与冲突检测不同。
  6. 排序返回副本,输出新建列表,不改传入子列表。将result直接指向输入第一个pair再修改其end,会悄悄修改调用方数据,测试需要检查输入保持不变。
  7. 单次批处理只要排序扫描;在线插入、删除或查询覆盖次数则需平衡树、区间树或差分等另行设计。静态并集不保留哪个原区间覆盖了某点,也无法直接回答删除一个原区间后的并集。

手动走一遍

[[1,10],[2,3],[10,12],[20,20]]先保留1至10,内层2至3不缩短,10至12相接后成[1,12],点20单独保留。[[1,2],[3,4]]不能合并,因为(2,3)未覆盖。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def merge_intervals(intervals):
    if any(len(pair) != 2 or pair[0] > pair[1] for pair in intervals):
        raise ValueError('intervals require start <= end')
    result = []
    for start, end in sorted(intervals):
        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);排序副本与最多n个输出区间O(n)空间。若已排序可O(n)扫描,但输出成本仍要计入。

易错点与追问

容易失分的边界

  • 嵌套时直接覆盖end导致区间缩短。
  • 闭区间相接误当分离。
  • 整数相邻无间隙的规则混入连续数轴。
  • 修改输入子列表,或宣称sort完全常量空间。

继续深挖

  • 半开区间合并与冲突检测分别怎样定?
  • 求总覆盖长度时点区间贡献多少?
  • 动态删除原区间要保留什么信息?
  • 怎样输出每个覆盖段的来源区间集合?
✓已复制微信号!