leetcode 253 会议室II
题目描述
There are n meetings, and the start time and end time of i-th meeting are s i s_i si and e i e_i ei. Please design a greedy algorithm to find the minimum number of meeting rooms required to arrange all meetings.
给定一个会议时间安排的数组,每个会议时间都会包括开始和结束的时间 [[s1,e1],[s2,e2],…] (si < ei), 为避免会议冲突,同时要考虑充分利用会议室资源,请你计算至少需要多少间会议室,才能满足这些会议安排。
Input: [ [0, 20], [15, 20], [20, 23], [25, 30], [15, 25] ]
Output: 3
- 算法标签
- 贪心
- 堆
错误的尝试
- 这题有一个类似的题目是安排不冲突的最多的会议,那题的思路是对结束时间从早到晚排序,然后看到这个题目就思维定式了,啪的一下,很快啊就错了
- 给一个反例
-
- 这种情况最少数量是2个,1和2复用一间会议室,3和4复用.
- 如果根据结束时间从早到晚,那么首先4会和1尝试合,发现冲突,于是4和2合,其余都合不了,总共3间,并不是最优解
-
贪心解法
- 用一个vector记录现有会议室的结束时间 e n d T i m e L i s t endTimeList endTimeList
- 对所有会议按照开始时间从早到晚排序
- 遍历所有的会议 a i a_i ai,在当前会议室集合 e n d T i m e L i s t endTimeList endTimeList找最早结束的会议 a e a r l i s t a_{earlist} aearlist,判断 a e a r l i s t a_{earlist} aearlist的结束时间是否早于 a i a_i ai的开始时间,如果早于则说明会议室能复用,在 e n d T i m e L i s t endTimeList endTimeList中更新改会议室的结束时间.否则则新开一间会议室,在 e n d T i m e L i s t endTimeList endTimeList中记录.
- 时间复杂度为 O ( n 2 ) O(n^2) O(n2)
#include <bits/stdc++.h>
//#define debug
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N = 100;
PII a[N];
vector<int> end_time_list;//现有会议室的结束时间集合
int main() {
#ifdef debug
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0);
int n = 0;
while (true) {
int t1, t2;
cin >> t1 >> t2;
if (!t1 && !t2)break;
a[n++] = {t1, t2};
}
sort(a, a + n, [&](PII p1, PII p2) { return p1.x < p2.x; });
for (int i = 0; i < n; ++i) {
int idx = 0;//最早结束会议室的下标
for (int j = 0; j < end_time_list.size(); ++j) {
//找最早结束的会议
if (end_time_list[j] < end_time_list[idx]) idx = j;
}
if (end_time_list.size() && end_time_list[idx] <= a[i].x)//当前会议的开始时间在最早结束的后面,可以复用会议室
end_time_list[idx] = a[i].y;
else //不能复用,新增一个会议室
end_time_list.push_back(a[i].y);
}
cout << end_time_list.size() << endl;
return 0;
}
堆优化解法
- 从一个集合中找最小值并且更新的操作可以用堆在 O ( log n ) O(\log n) O(logn)的时间复杂度内完成
- 用C++中的优先队列实现小顶堆
#include <bits/stdc++.h>
//#define debug
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N = 100;
PII a[N];
priority_queue<int, vector<int>, greater<int>> heap;//最早的结束时间
int main() {
#ifdef debug
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0);
int n = 0;
while (true) {
int t1, t2;
cin >> t1 >> t2;
if (!t1 && !t2)break;
a[n++] = {t1, t2};
}
sort(a, a + n, [&](PII p1, PII p2) { return p1.x < p2.x; });
for (int i = 0; i < n; ++i) {
if (!heap.empty() && heap.top() <= a[i].x) {
//复用会议室
heap.pop();
}
heap.push(a[i].y);
}
cout << heap.size() << endl;
return 0;
}