题目重点:相同Job重叠允许共享,与每个实例独占Server是两种模型。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 每个(type,start,duration)每天周期P重复;相同type重叠合并忙区间,duration≥P则该type全天忙。
- 代码返回同时活跃不同type的峰值容量,允许时刻边界无代价迁移/重新分配。若Job必须固定绑定物理Server全程不迁移,循环区间着色另求,不能把峰值直接当充分答案。
解题路线
- 每条周期区间切为[0,P)内一段或跨午夜两段;同type先合并重叠及相接,不能跨类型合并。
- 各type并集端点加+1/−1,同时间合并事件后求峰值;半开端点结束即释放,不多算瞬间重叠。长于一天同type的重复覆盖完整周期,只需要一个同时活跃类型计数。
- 固定绑定模型的循环弧可能形成三个类型两两相交却无三者同点,峰值2但冲突图需3色。若面试要求最少固定Server,必须解决该模型或明确可切段调度条件。
手动走一遍
A从22持续4、P24,切[22,24)+[0,2);另一A从0持续1合并,不多占。A持续30≥24全天忙,B只[4,5)忙,峰值2。不同类型实例仍不能合并。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
from collections import defaultdict
def servers(jobs,period):
# Repeating (job_type, start, duration), same type overlaps share one server.
if period<=0:raise ValueError("positive period")
by_type=defaultdict(list)
for job,start,duration in jobs:
if duration<0:raise ValueError("negative duration")
if duration==0:continue
start%=period
if duration>=period:by_type[job].append((0,period));continue
end=start+duration
if end<=period:by_type[job].append((start,end))
else:by_type[job].extend(((start,period),(0,end-period)))
events=defaultdict(int)
for intervals in by_type.values():
merged=[]
for a,b in sorted(intervals):
if merged and a<=merged[-1][1]:merged[-1]=(merged[-1][0],max(b,merged[-1][1]))
else:merged.append((a,b))
for a,b in merged:events[a]+=1;events[b]-=1
active=answer=0
for time in sorted(events):active+=events[time];answer=max(answer,active)
return answer
复杂度
n记录排序并集O(nlogn)、事件O(nlogn),空间O(n);峰值容量不含固定绑定着色结果。
易错点与追问
容易失分的边界
- 单独把跨日切段视独立Job会给同type重复计数。
- 固定绑定约束下用并发峰值承诺最少Server可能错误。
继续深挖
- 若同type有两个版本且不能共享,如何构造真正合并键?
- 禁止迁移时如何从区间冲突图给下界、可行上界及小规模精确解?
