253. 会议室 II(中等)
题目
给定若干场会议,每场用 [开始时间, 结束时间) 表示;问:要让所有会议都能按时开完,最少需要准备多少间会议室。
换句话说:在任意一个时刻,数一数同时有多少场会议正在进行;这个“同时进行”的最大值,就是答案。
自造示例:[[1,4],[2,5],[4,7],[6,9]] → 2(第 1、2 场重叠需要 2 间;[4,7] 在 4 点接上刚结束的 [1,4],[6,9] 在 6 点接上已结束的 [2,5])。
再看一个需要 3 间的示例:[[0,3],[1,4],[2,5],[3,6]] → 3(在 2.5 时,[0,3]、[1,4]、[2,5] 同时进行)。
约束:会议数 0 ~ 104;每场恰有两个整数,0 ≤ 开始时间 < 结束时间 ≤ 106。
思路
一句话:最少会议室数 = 同一时刻同时进行的会议数的最大值;所以问题变成求时间轴上的“最高水位”。
最直白的做法:把时间轴打成一格一格,从 0 秒到最大结束时间逐时刻统计正在进行多少场会议。若最大结束时间记为 M,这样做要 O(M) 次扫描;M 到 106 还能做,但 M 更大就崩,何况大量“没有任何会议变化”的时刻是重复劳动。
关键观察:并发人数只会在某场会议开始或某场会议结束的瞬间发生变化。因此只需把每个会议拆成两个事件:开始 +1、结束 -1,按时间排序后从左到右累加,过程中出现的最大值就是答案。这就是扫描线 / 差分思路。
另一个更直观的思考:先把会议按开始时间排序。处理一个新会议时,只关心当前最早空出来的房间够不够早:若最早结束时间 ≤ 当前开始时间,就直接复用那个房间;否则只能开新房间。要持续拿到“最早结束时间”,用小根堆最合适。
于是做法确定为:按开始时间排序 + 小根堆维护当前正在使用的所有房间的结束时间。
解法
把每一间会议室看成一个“被占用的时间槽”,房间里记录它什么时候结束;小根堆堆顶 top 就是这些房间里最早结束的那个时间。
- 把
intervals按开始时间升序排序;空数组直接返回0。 - 准备一个空的小根堆
pq,存放当前已占用会议室的结束时间。 - 遍历每个
[start, end]:- 若
start ≥ pq.top(),说明最早结束的房间已经空出,弹出它(用≥,因为 4 点结束、4 点开始不算重叠)。 - 无论是否弹出,都把当前会议的
end入堆:它此刻占用了一个房间(复用的旧房间或新开的房间)。
- 若
- 遍历结束后,堆的大小就是所需会议室数的峰值。
| 当前会议 | 开始 | 堆顶(最早结束) | 能否复用? | 操作 | 操作后堆 |
|---|---|---|---|---|---|
| [1,4] | 1 | 空 | — | 入 4 | [4] |
| [2,5] | 2 | 4 | 2 ≥ 4 ? 否 | 入 5 | [4,5] |
| [4,7] | 4 | 4 | 4 ≥ 4 ? 是 | 出 4、入 7 | [5,7] |
| [6,9] | 6 | 5 | 6 ≥ 5 ? 是 | 出 5、入 9 | [7,本篇为付费内容您已阅读试读部分,购买后即可解锁全文。 ⚠️ 本站内容已做唯一性标记并受版权保护,未经授权禁止转载,侵权必究。 |
还没有评论,来说两句?