LeetCode 252 会议室 III(Meeting Rooms III)题解与模拟面试

1. 引言

在现代办公和协作中,会议室的高效利用至关重要。LeetCode 252 题"会议室 III"要求我们在给定一组会议的时间区间后,计算同一时间段内需要开的最少会议室数量,以保证所有会议能顺利进行。本题不仅是经典的区间调度问题变形,也常见于资源分配、调度系统等实战场景。

标签:

  • 堆(Heap)
  • 排序(Sort)
  • 贪心(Greedy)

应用场景:

当系统中需动态分配资源(如服务器、房间、工程师),如何最小化资源数量而满足并发需求。该思路可推广到云计算资源调度、任务池管理等领域。


2. 题目描述

给定一个会议时间列表 intervals,其中 intervals[i] = [start_i, end_i] 表示第 i 场会议的开始时间和结束时间(不含结束端点)。请你计算并返回同时进行的会议的最大数量,也就是需要开的最少会议室数量。

示例函数签名(Python)

python 复制代码
def minMeetingRooms(intervals: List[List[int]]) -> int:
    pass
  • 输入 :二维整数数组 intervals,长度范围 [0, 10^4]
  • 输出:整数,最少会议室数量。

3. 示例分析

示例 1

复制代码
输入:[[0,30],[5,10],[15,20]]
输出:2
  • 解释:会议 [0,30] 与 [5,10] 时间重叠,需要 2 个房间;[15,20] 可复用 [5,10] 结束的房间。

示例 2

复制代码
输入:[[7,10],[2,4]]
输出:1
  • 解释:没有重叠,所有会议可在同一房间举行。

4. 问题建模与关键点

  1. 区间调度:本题属于「同时进行的区间最大重叠数」问题,经典解法是通过排序和优先队列统计并发量。
  2. 数据结构映射
    • 将每个会议的结束时间入堆,堆顶保存当前最早结束的会议。
    • 遍历开始时间,从堆中弹出所有已结束的会议,堆的大小即为当前并发会议数。

5. 解题思路

  1. 暴力枚举:对每一个分割点遍历所有区间,时间复杂度 O(n²),不推荐。
  2. 最小堆 + 排序
    • 按会议开始时间升序排序。
    • 使用最小堆维护各会议的结束时间。
    • 对每个会议,比较堆顶结束时间与当前会议开始时间:
      • 若堆顶 ≤ 当前开始,说明该会议室已空,将堆顶弹出并复用。
      • 否则需新开会议室。
    • 将当前会议的结束时间入堆。
    • 堆的大小即为所需会议室数。

为什么用堆?

  • 堆能在 O(log n) 内获得并更新最小结束时间,使整体复杂度保持 O(n log n)。

6. 算法流程

  1. intervals 为空,返回 0。
  2. 将所有会议按 start 升序排序。
  3. 初始化最小堆 heap = []
  4. 遍历 intervals
    • heap 非空且 heap[0] ≤ current_start,弹出堆顶(复用会议室)。
    • 否则无需操作(开新会议室)。
    • current_end 入堆。
  5. 遍历结束后,len(heap) 即为答案。

7. 代码实现

Python 版本

python 复制代码
from typing import List
import heapq

def minMeetingRooms(intervals: List[List[int]]) -> int:
    if not intervals:
        return 0
    # 按开始时间排序
    intervals.sort(key=lambda x: x[0])
    # 最小堆存储会议结束时间
    heap = []
    for start, end in intervals:
        # 如果有空闲会议室
        if heap and heap[0] <= start:
            heapq.heappop(heap)
        # 将当前会议结束时间加入堆中
        heapq.heappush(heap, end)
    return len(heap)

Java 版本

java 复制代码
import java.util.*;

class Solution {
    public int minMeetingRooms(int[][] intervals) {
        if (intervals == null || intervals.length == 0) return 0;
        Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));
        PriorityQueue<Integer> heap = new PriorityQueue<>();
        for (int[] interval : intervals) {
            if (!heap.isEmpty() && heap.peek() <= interval[0]) {
                heap.poll();
            }
            heap.offer(interval[1]);
        }
        return heap.size();
    }
}

8. 复杂度分析

  • 时间复杂度:排序 O(n log n) + 遍历 n 次,每次堆操作 O(log n),总体 O(n log n)。
  • 空间复杂度:最坏情况下所有会议重叠,堆中有 n 个元素,O(n)。

9. 边界情况 & 优化思考

  1. 空列表:直接返回 0。
  2. 单个会议:返回 1。
  3. 所有会议无重叠:堆大小最高保持 1。
  4. 大量重叠:堆大小趋近 n。
  5. 优化内存有限场景:可将结束时间存入有序数组并使用双指针,牺牲部分时间性能以节省堆空间。

10. 总结

  • 本题为区间调度经典变形,核心在于统计最大并发区间数。
  • 利用最小堆维护最早结束时间,实现 O(n log n) 解决。
  • 模板可复用于「会议室 II」「区间交集」「区间插入」等相关题目。

11. 模拟面试

在面试中,本题常作为考察区间调度与堆应用的典型题目。

面试题型示例

  1. 题目复述:给定一组会议时间区间,求所需的最少会议室数。
  2. 核心考点:区间排序、最小堆维护、复杂度分析。
  3. 扩展追问
    • 如果数据量达到 10⁸ 条,如何优化?
    • 在内存受限时,双指针法如何替代堆?
    • 多线程场景下,如何并行调度?

答题建议流程

  • 明确题意:复述输入输出,例举小规模示例。
  • 思路阐述:先讲排序,再说明堆的作用和复用机制。
  • 手写伪码:关键操作集中在堆弹出与入堆两步。
  • 复杂度分析:O(n log n) 时间,O(n) 空间。
  • 优化讨论:根据场景提出双指针、流式处理或并行方案。
相关推荐
沐怡旸1 小时前
【算法】【链表】328.奇偶链表--通俗讲解
算法·面试
掘金安东尼5 小时前
Amazon Lambda + API Gateway 实战,无服务器架构入门
算法·架构
码流之上5 小时前
【一看就会一写就废 指间算法】设计电子表格 —— 哈希表、字符串处理
javascript·算法
快手技术7 小时前
快手提出端到端生成式搜索框架 OneSearch,让搜索“一步到位”!
算法
CoovallyAIHub1 天前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
NAGNIP1 天前
Serverless 架构下的大模型框架落地实践
算法·架构
moonlifesudo1 天前
半开区间和开区间的两个二分模版
算法
moonlifesudo1 天前
300:最长递增子序列
算法
CoovallyAIHub1 天前
港大&字节重磅发布DanceGRPO:突破视觉生成RLHF瓶颈,多项任务性能提升超180%!
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
英伟达ViPE重磅发布!解决3D感知难题,SLAM+深度学习完美融合(附带数据集下载地址)
深度学习·算法·计算机视觉