SWE · Coding

TikTok 最少会议室:结束时间堆与同刻交接规则

按开始排序,释放所有已结束会议,用最大同时占用数证明最少房间数。

题目重点:按开始排序,释放所有已结束会议,用最大同时占用数证明最少房间数。

题意与假设

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

  • 训练会议为半开区间[start,end),要求start<end;end等于另一会议start时可以复用房间。
  • 时间戳可比较,代码例子使用数值;空输入返回0,输入列表保持不变。
  • 只返回房间数,不输出分配表;准备/清洁间隔与零长度会议政策需另确认。

解题路线

  1. 最少房间数下界是任一时刻同时进行的会议数:这些会议不能共享房间。本题还要证明能达到下界,而不只是统计区间个数。
  2. 按开始时间排序,用小根堆保存正在占用房间的会议结束时间。当前会议start到来时,把所有end≤start的元素弹出,剩余的正是与新会议重叠的已开始会议。
  3. 然后把当前end加入堆,并更新堆大小的最大值。这个版本的堆含活跃会议,并不保存所有曾分配的房间;最终堆大小可能很小,答案必须是历史最大值。
  4. 在某个start时刻堆达到k,表示实际存在k个同时进行的会议,给出k房间的下界;每当某会议开始,没有空房才增加房间,否则复用已释放房间,最多需要该峰值,证明下界可达。
  5. 也可以维护所有房间的最早释放时间,每次最多复用一个,然后最终堆大小就是房间总数;那是另一个不变量。不要把两个版本混起来:本代码释放所有过期项,最后堆大小不是答案。
  6. 同一时刻的交接由半开合同决定。若改为闭区间或要求清洁延迟,end=start的两个会议可能不能复用;比较符号或effective_end需要随合同改变。
  7. 扫线版先分别排序开始和结束,同刻先处理结束,同样得到最大占用。独立验证可直接在每个开始时间数满足start≤t<end的区间,不依赖堆或排序实现。

手动走一遍

[(0,30),(5,10),(15,20)]在5时有两场,答案2;到15时10结束,释放后再加入20。[(1,2),(2,3)]可交接,答案1;第二场加入后最终堆大小1,但前例若最后只剩一场仍必须返回历史峰值2。

Python 参考实现

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

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

import heapq


def minimum_rooms(intervals):
    if any(len(pair) != 2 or pair[0] >= pair[1] for pair in intervals):
        raise ValueError('meetings require start < end')
    ending = []
    best = 0
    for start, end in sorted(intervals):
        while ending and ending[0] <= start:
            heapq.heappop(ending)
        heapq.heappush(ending, end)
        best = max(best, len(ending))
    return best

复杂度

n场会议排序O(n log n),每个会议入堆出堆最多一次,总时间O(n log n);排序副本和堆O(n)空间。已按开始排好时可省排序但堆界不变。

易错点与追问

容易失分的边界

  • 最终活跃堆大小当作总房间数。
  • 半开合同使用end<start导致同刻多算房间。
  • 只释放一个却仍解释为所有活跃会议。
  • 零长度会议未定义就悄悄参与占用。

继续深挖

  • 怎样返回每场会议的房间编号?
  • 每场还要清洁时间如何修改?
  • 在线乱序新增/取消会议怎样维护最大重叠?
  • 不同房间容量和会议人数约束为何不是简单重叠数?
✓已复制微信号!