SWE · Coding

恰有X场会议的全部区间:按事件差分扫描

不是仅求最高并发,也不是仅X=1。

题目重点:不是仅求最高并发,也不是仅X=1。

题意与假设

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

  • 半开区间start<end,目标X正整数;输出最大相接合并时间段。
  • X0需有限查询域,否则两端无限空闲,本代码拒绝;同一人多重记录不自动去重。

解题路线

  1. 每开始+1结束−1,先把同timestamp delta合并。在相邻不同事件点[t,next)内active常数,若等X加入。
  2. 相接满足段合并:一个会议结束另一个开始净delta0,active仍X,可以连成更长段。不能把同点中间处理状态输出成正长度段。
  3. 与每person恰覆盖一次的题不同,这里每会议记录占一个单位。若要按人去重,必须先合并每人的重叠区间再扫描。

手动走一遍

[1,3)、[2,4),X1输出[1,2)和[3,4),X2输出[2,3)。[1,2)、[2,3),X1输出[1,3),中间无空隙。

Python 参考实现

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

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

from collections import defaultdict

def segments(intervals,target):
    if target<=0:raise ValueError("positive target; zero needs a query domain")
    events=defaultdict(int)
    for a,b in intervals:
        if a>=b:raise ValueError("positive-duration half-open interval")
        events[a]+=1;events[b]-=1
    times=sorted(events);active=0;answer=[]
    for i,t in enumerate(times[:-1]):
        active+=events[t];end=times[i+1]
        if active==target:
            if answer and answer[-1][1]==t:answer[-1]=(answer[-1][0],end)
            else:answer.append((t,end))
    return answer

复杂度

n会议O(nlogn)时间/O(n)事件及输出空间。

易错点与追问

容易失分的边界

  • closed端点语义会有孤立点,不能不加说明套半开。
  • 求≥X与==X输出不同。

继续深挖

  • 在线add/delete时能否维护整条并发曲线?
  • 按最大并发值返回所有段时怎样一遍或两遍扫描?
✓已复制微信号!