题目重点:先用可用时刻分配任务,再加入 worker 技能过滤和账号亲和;旧 worker 不支持任务类型时回退最早可接选择。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版 tasks 按给定顺序到达,全部最早在 0 时可开始;每个 task 有正耗时 duration、type 和可选 account。worker 同时只做一个任务。
- ‘最快能接手’定义为最小可用时间,若并列取较小 worker ID;技能仅决定能否处理,不改变 duration。若实际题面给到达时刻 r,开始时间应为 max(r,available_at)。
- account 粘性只在已关联 worker 支持新 task type 时强制使用;不支持时选符合技能的最早 worker 并将 account 绑定更新到新 worker。题目只说重新分配,是否更新绑定需现场确认。
解题路线
- Part 1 维护每个 worker 的 available_at,取最小 (available_at,id),输出分配并加 duration。小规模可 O(W) 扫描;大规模用堆,但弹出后必须写回新 available_at。
- Part 2 对当前 task type 只考虑支持它的 worker;若没有候选则按题面报未分配,不默默给不支持者。若只有静态技能集合,可以按 type 建候选堆,但一个 worker 被其它类型任务占用时需要版本号去掉陈旧堆项。
- Part 3 先查 account→worker;支持 type 则即使该 worker 等待更久也按粘性路由。否则回退 Part 2,并按训练合同更新绑定。必须在每次分配后修改同一份 worker 时钟,不能为各类技能维护互不一致的负载。
- 测试同可用时刻、不同耗时、无技能候选、粘性导致延迟、旧 worker 不支持类型、账号首次出现及任务为空;若所有任务同 0 到达,任务顺序本身会影响结果。
手动走一遍
训练例 W0/W1 均 0 可用,任务 A 用时 5 分给 W0,任务 B 用时 2 分给 W1;之后 account X 的 type=t 若上次给 W0 且 W0 支持 t,就仍给 W0,哪怕 W1 在时刻 2 空闲,而 W0 到时刻 5 才空。若 W0 不支持 t,回退选择 W1。
规模与取舍
T 个任务、W 个 worker:简单扫描 O(TW) 时间、O(W+A) 状态空间(A 个 account);每类型堆可降常见选择为 O(log W),但跨类型 worker 占用造成陈旧键,需要额外版本维护和内存。
易错点与追问
容易失分的边界
- 把最早完成任务误写成当前负载最小或 worker ID 最小。
- 技能过滤发生在选 worker 之后,结果选到不支持类型者。
- 粘性 worker 忙就擅自换人,即使原题要求强制同账号。
- 只更新某个 type 的堆而不更新其它 type 的同 worker 可用时刻。
- 无到达时刻信息却编造抢占、截止时间或优先级规则。
继续深挖
- 如果任务有 arrival_time,空闲但尚未到达的任务如何排?
- 账号粘性让长任务集中一台时,可否设置最大等待阈值来打破亲和?
- 若 worker 的技能随时间变化,如何维护可用集合而不重建全部堆?
