SWE · Coding

Meta 最多区间重叠的位置:闭端点事件顺序

返回覆盖区间数最多的坐标,用扫描线处理同坐标起止,明确并列和闭区间边界。

题目重点:返回覆盖区间数最多的坐标,用扫描线处理同坐标起止,明确并列和闭区间边界。

题意与假设

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

  • 训练区间闭合[left,right],left≤right,返回(point,count);并列取最早坐标,空输入(None,0)。若题面为半开区间,事件顺序和点区间规则不同。

解题路线

  1. 分别累计每坐标startCount和endCount,排序所有不同端点。扫描到x先加起点,再计算峰值,最后减终点;闭区间终点在x仍参与覆盖。
  2. active表示从前坐标到x之前仍活跃的区间,加start后准确等于包含x的区间数。结束事件必须在观察后减去,否则[1,2]与[2,3]会漏掉x2共同覆盖。
  3. 为何只看端点足够?开区间间隔内覆盖数不变,新增覆盖只在起点发生;任意最大覆盖区段的最早合法点可取起点。因此端点扫描能找到全局最大并列最早。
  4. 只在active>best时更新point,sorted顺序自动保留最早;同坐标多个点区间同时start/end,先加后减也成立,不需要特殊分支。
  5. 如果题面只要number坐标,可只返回point;count用于检查与解释。不要返回最大数量替代位置,输出合同应明确。

手动走一遍

[1,2]、[2,3]、[2,2]在x2同时覆盖3个,返回(2,3)。[1,2]与[3,4]最大1,并列返回1;边界若半开则x2不再同时覆盖前两个,需要改合同。

Python 参考实现

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

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

from collections import defaultdict


def maximum_overlap(intervals):
    """Closed intervals; returns (earliest max-count point,count), empty (None,0)."""
    starts=defaultdict(int);ends=defaultdict(int)
    for left,right in intervals:
        if left>right:raise ValueError('reversed interval')
        starts[left]+=1;ends[right]+=1
    active=best=0;point=None
    for x in sorted(starts.keys() | ends.keys()):
        active+=starts[x]
        if active>best:best=active;point=x
        active-=ends[x]
    return point,best

复杂度

O(N log N)时间/O(N)事件空间,扫描O(不同端点数)。若时间轴很大不可开长度为最大坐标的数组;压缩排序端点不依赖坐标数值范围。

易错点与追问

容易失分的边界

  • 闭区间先减end会漏端点共同覆盖。
  • 把最大重叠坐标与最少会议室/箭数量混成同输出。

继续深挖

  • 若求所有最大覆盖区段,怎样保留端点和开闭信息?
  • 在线添加删除区间,可用坐标压缩segment tree维护范围加和最大值,但未知新坐标如何处理?
✓已复制微信号!