☰
【贪心-2】253.会议室 II
2026/10/2 15:13:03 网站建设 项目流程

题目描述:

给定一个会议时间安排的数组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 ✅

代码实现:

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+111
5+122
10-112
15+122
20-112
30-102

结果:2✅

代码实现:

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++

代码实现:

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)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询