SDE Intern / NG · OA

Amazon OA:查询区间里,恰好 K 个进程运行多少秒?

把闭区间结束移到end+1事件,按并发数建立压缩长度前缀,支持巨大时间与零并发。

题目重点:把闭区间结束移到end+1事件,按并发数建立压缩长度前缀,支持巨大时间与零并发。

题意与假设

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

  • 整数秒,每过程占[start,end],每查询也含两端;start≤end,k非负。
  • 查询可在所有进程生命周期外,k=0仍须统计;空过程和无查询分别处理。

解题路线

  1. 事件start:+1,end+1:-1;排序事件点后,在at应用变化,得到[at,next)每个整数秒的并发数k,长度next-at。
  2. 把相同k的段放进自己的starts/ends列表并累积长度。F_k(t)表示所有这些段中严格小于t的秒数,二分定位最后start≤t段,完整此前段加当前截断长度。
  3. 查询结果F_k(r+1)-F_k(l),用r+1统一闭区间。t落两个同k段之间的空隙要截到上一段end,而不是持续加长度。
  4. horizon与limit覆盖全部过程及所有查询范围,加入0变化端点,从而生命周期前后可形成k=0段。缺此边界会漏整个空闲时段。
  5. 时间跨度到10^15仍只有O(n)变化段。作者密集差分在小时间范围可行,但不能用maxTime大小开数组解决无界坐标;查询k>n无段自然0。

手动走一遍

训练进程[1,2]与[2,4],并发1在秒1、3、4,并发2在秒2;query(1,1,4)=3,query(0,0,5)=2,即秒0和5。

Python 参考实现

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

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

from collections import defaultdict
from bisect import bisect_right


def exact_concurrency_seconds(processes,queries):
    """Inclusive integer process intervals and queries (k,left,right)."""
    if any(s>e for s,e in processes) or any(k<0 or l>r for k,l,r in queries):
        raise ValueError("invalid interval or concurrency")
    if not queries:return []
    delta=defaultdict(int)
    for start,end in processes:
        delta[start]+=1
        delta[end+1]-=1
    horizon=min([l for k,l,r in queries]+[s for s,e in processes])
    limit=max([r+1 for k,l,r in queries]+[e+1 for s,e in processes])
    delta[horizon]+=0
    delta[limit]+=0
    points=sorted(delta)
    groups={}
    active=0
    for at,nxt in zip(points,points[1:]):
        active+=delta[at]
        starts,ends,prefix=groups.setdefault(active,([],[],[0]))
        starts.append(at)
        ends.append(nxt)
        prefix.append(prefix[-1]+nxt-at)
    def measure_before(k,time):
        if k not in groups:return 0
        starts,ends,prefix=groups[k]
        i=bisect_right(starts,time)-1
        if i<0:return 0
        return prefix[i]+min(time,ends[i])-starts[i]
    return [measure_before(k,r+1)-measure_before(k,l) for k,l,r in queries]

复杂度

n过程、q查询,O(n log(n+1)+q log(n+1))时间、O(n+q)输入/输出及O(n)段状态,独立于时间数值宽度。

易错点与追问

容易失分的边界

  • end处减一漏最后一秒。
  • 查询闭区间用F(r)漏r。
  • k=0没建外部空闲范围。
  • 同k两段间空隙误计。

继续深挖

  • 在线新增过程怎样改变索引?
  • 连续实数时间应怎样改长度定义?
  • 只查高并发区间可否省存部分桶?
✓已复制微信号!