【贪心-2】253.会议室 II

题目描述:

给定一个会议时间安排的数组 intervals,每个会议时间包括开始和结束的时间 [start, end],计算至少需要多少间会议室才能满足所有会议安排。

示例:

复制代码
输入: [[0, 30], [5, 10], [15, 20]]
输出: 2

输入: [[7, 10], [2, 4]]
输出: 1

解题思路:

方法一:排序 + 小根堆(推荐)

核心思路:

  1. 按开始时间排序所有会议

  2. 用小根堆 维护当前正在使用的会议室的结束时间

  3. 遍历每个会议:

    • 如果堆顶(最早结束的会议)≤ 当前会议的开始时间,说明有会议室空闲,弹出堆顶

    • 把当前会议的结束时间压入堆

  4. 堆的大小就是所需的最少会议室数量

具体过程示例:

intervals = [[0, 30], [5, 10], [15, 20]]

排序后:[[0, 30], [5, 10], [15, 20]]

会议 堆操作 堆内容 说明
0, 30 push(30) 30 第一间会议室
5, 10 堆顶30 > 5,push(10) 10, 30 需要第二间
15, 20 堆顶10 ≤ 15,pop,push(20) 20, 30 复用第一间

堆大小 = 2 ✅

代码实现:

cpp 复制代码
class Solution {
public:
    int minMeetingRooms(vector<vector<int>>& intervals) {
        if (intervals.empty()) return 0;
        
        // 按开始时间排序
        sort(intervals.begin(), intervals.end());
        
        // 小根堆,存储结束时间
        priority_queue<int, vector<int>, greater<int>> pq;
        
        for (auto& interval : intervals) {
            // 如果有会议室空闲,弹出最早结束的
            if (!pq.empty() && pq.top() <= interval[0]) {
                pq.pop();
            }
            pq.push(interval[1]);
        }
        
        return pq.size();
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n log n) 排序 + 每个会议一次堆操作
空间复杂度 O(n) 堆最多存储 n 个结束时间

方法二:扫描线

思路:

把每个会议拆成两个事件:

  • 开始:+1(需要一间会议室)

  • 结束:-1(释放一间会议室)

按时间排序所有事件,累加计数,最大值就是所需会议室数。

关键 :同一时间有开始和结束,结束优先处理(先释放再占用)。

具体过程示例:

intervals = [[0, 30], [5, 10], [15, 20]]

事件:(0,+1), (5,+1), (10,-1), (15,+1), (20,-1), (30,-1)

时间 事件 计数 最大值
0 +1 1 1
5 +1 2 2
10 -1 1 2
15 +1 2 2
20 -1 1 2
30 -1 0 2

结果:2 ✅

代码实现:

cpp 复制代码
class Solution {
public:
    int minMeetingRooms(vector<vector<int>>& intervals) {
        vector<pair<int, int>> events;
        for (auto& interval : intervals) {
            events.push_back({interval[0], 1});   // 开始
            events.push_back({interval[1], -1});  // 结束
        }
        
        // 按时间排序,同一时间结束优先(-1 在前)
        sort(events.begin(), events.end(), [](const pair<int,int>& a, const pair<int,int>& b) {
            if (a.first == b.first) return a.second < b.second;
            return a.first < b.first;
        });
        
        int count = 0, maxRooms = 0;
        for (auto& [time, delta] : events) {
            count += delta;
            maxRooms = max(maxRooms, count);
        }
        
        return maxRooms;
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n log n) 排序事件
空间复杂度 O(n) 事件数组

方法三:双指针

思路:

把开始时间和结束时间分别排序,用两个指针比较:

  • 如果 start[s] < end[e]:新会议开始,需要新会议室,count++,s++

  • 否则:有会议结束,释放会议室,count--,e++

代码实现:

cpp 复制代码
class Solution {
public:
    int minMeetingRooms(vector<vector<int>>& intervals) {
        int n = intervals.size();
        vector<int> starts(n), ends(n);
        
        for (int i = 0; i < n; i++) {
            starts[i] = intervals[i][0];
            ends[i] = intervals[i][1];
        }
        
        sort(starts.begin(), starts.end());
        sort(ends.begin(), ends.end());
        
        int s = 0, e = 0, count = 0, maxRooms = 0;
        while (s < n) {
            if (starts[s] < ends[e]) {
                count++;
                s++;
            } else {
                count--;
                e++;
            }
            maxRooms = max(maxRooms, count);
        }
        
        return maxRooms;
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n log n) 排序两个数组
空间复杂度 O(n) 两个辅助数组

三种方法对比:

方法 时间复杂度 空间复杂度 代码复杂度 推荐度
排序 + 小根堆 O(n log n) O(n) 中等 ⭐⭐⭐⭐⭐
扫描线 O(n log n) O(n) 中等 ⭐⭐⭐⭐
双指针 O(n log n) O(n) 简单 ⭐⭐⭐⭐

总结:

要点 说明
核心思想 求重叠会议的最大数量
最优解法 排序 + 小根堆(维护结束时间)
关键操作 堆顶 ≤ 当前开始时间 → 复用会议室
时间复杂度 O(n log n)
空间复杂度 O(n)
相关推荐
垆边人似月.1 小时前
华为机考题(一):质数因子
算法·华为
重生之小比特1 小时前
【C++进阶】异常
开发语言·c++
朝朝辞暮i1 小时前
C++ 第 15 课:指针 * 和地址 &
开发语言·c++
奶茶树1 小时前
【C++】14. C++11新特性【下】
开发语言·c++
迷途之人不知返1 小时前
算法系列5:位运算
算法
牢姐与蒯1 小时前
c++加餐之位图
c++·算法·哈希
苏辰澈2 小时前
C++自己的族谱规则:继承详解上
c语言·c++·visualstudio
Omics Pro2 小时前
预测性虚拟细胞中显式机理算子
大数据·数据库·人工智能·python·算法·机器学习·自然语言处理
驭渊的小故事2 小时前
算法实战:滑动窗口、素数枚举与字符串模拟(三道经典题解)
java·算法