题目描述
有n个活动即将举办,每个活动都有活动的开始时间与活动的结束时间,第i个活动的开始时间是start_i,第i个活动的结束时间是end_i,举办某个活动就需要为该活动准备一个活动主持人。一位活动主持人在同一时间只能参与一个活动。并且活动主持人需要全程参与活动,换句话说,活动主持人参与了第i个活动,那么该主持人在start_i,end_i 这个时间段不能参与其他任何活动。求为了成功举办这n个活动,最少需要多少名主持人。
示例1
输入 2,[[1,2],[2,3]]
返回值 1
说明:只需要一个主持人就能成功举办这两个活动
示例2
输入 2,[[1,3],[2,4]]
返回值 2
说明:需要两个主持人才能成功举办这两个活动
题解:
主持人不能一人分饰两角,也就是不能在相交的区间里工作,本题目就是要将这些相交的区间分组,在这个组里的就是那些没有交集的。最后主持人的数量就是分组的数量。
- 区间分组,在组内区间不相交的前提下,分成尽可能少的组。而不是尽可能多的组,因为一个区间一组,就是尽可能多组的答案。
- 首先需要对集合中的区间按照左端点进行排序,然后分别比较已经存在的分组中最小的右端点 r 和当前参与比较的区间的左端点 l ,如果 r > l ,那么该区间与存在的分组有交集,需要新开一个分组。
- 在选择数据结构上,可以看到需要将存在的分组中最小的右端点不断更新并且需要添加新的分组进去,这种动态的性质就决定了使用堆这一数据结构,并且如果说当前所有分组中最小的比 l 还大的话,那么其余的一定比 l 大,因此使用小根堆。
- heap.top > line.l 当前区间的左端点比最小的右端点还要小,也就是已经有交集的部分了,那么放到任何一组都会有相交部分,注意前提这些区间已经是排好序的。可以这么想,如果说当前区间与分组中其余部分没有交集,那么该区间遍历时一定会早于这就已经分好组的区间,与当前的情形矛盾,因此没有交集。
const int N=100010;
class Solution {
public:
struct Line
{
int l,r;
bool operator < (const Line &W) const{
return l<W.l;
}
}Lines[N];
int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {
// write code here
for(int i=0;i<n;i++)
{
Lines[i]={startEnd[i][0],startEnd[i][1]};
}
sort(Lines,Lines+n);
priority_queue<int,vector<int>,greater<int>> heap;
for(int i=0;i<n;i++)
{
auto line=Lines[i];
//有交集,新开一个分组
if(heap.empty()||heap.top()>line.l) heap.push(line.r);
else //没有交集,更新分组的max_r
{
heap.pop();
heap.push(line.r);
}
}
return heap.size();
}
};