题意:
给定多个区间和一个受感染的区间,问与受感染区间相交集的总个数。
(相交包含直接相交和间接相交)
方法一:
并查集(超时)
思路:这道题的核心是找 包含受感染区间 的最大连续区间的个数。利用并查集,将这些区间分割成多块不相交的集合,找到包含受感染区间的那个集合,并返回那个集合中的节点数量。
class Solution {
public:
int Find(int x,vector<int>& fa){//找一个集合中的队长节点
if(fa[x]!=x)
fa[x]=Find(fa[x],fa);
return fa[x];
}
int intersection(Point u,Point v){//两个区间是否相交
if(u.x<v.x){
return v.x<=u.y;
}else if(u.x<=v.y){
return 1;
}
return 0;
}
int CatchVirus(int Personid, vector<Point>& PeoplePosition) {
int n=PeoplePosition.size();
int res=0;
vector<int> fa(n);
vector<int> cnt(n);//记录各集合中节点个数
for(int i=0;i<n;i++){//初始化并查集
fa[i]=i;
cnt[i]=1;
}
for(int i=0;i<n;i++){//遍历每两个区间
for(int j=i+1;j<n;j++){
if(intersection(PeoplePosition[i],PeoplePosition[j])){//如果两区间相交,则合并为一个集合
int x=Find(i,fa);
int y=Find(j,fa);
if(x!=y){//如果两区间不在同一个集合中,则合并为同一个集合
fa[x]=y;
cnt[y]+=cnt[x];
}
}
}
}
return cnt[Find(Personid,fa)];//返回受感染的的最大连续区间的个数
}
};
时间复杂度:
空间复杂度:![]()
方法二:
贪心
思路:将所有区间按照左端点从小到大排序,并用维护区间右端点的最大值。
如果遇到受感染区间,标记一下。
最后返回 包含受感染区间 的最大连续区间的个数。
class Solution {
public:
int CatchVirus(int Personid, vector<Point>& PeoplePosition) {
int n=PeoplePosition.size();//区间个数
int num=0;//相交区间数量
int r=0;//维护的区间右端点的最大值
int flag=0;//判断是否找到Personid的区间
Point t=PeoplePosition[Personid];
sort(PeoplePosition.begin(),PeoplePosition.end(),[](Point &a,Point &b){return a.x<b.x;});
for(int i=0;i<n;i++){
if(r<PeoplePosition[i].x){//重新开始一段连续相交区间
if(flag==1)//如果遇到感染区间,退出循环
break;
r=PeoplePosition[i].y;
num=1;
}else{
r=max(r,PeoplePosition[i].y);
num++;//连续相交区间个数加一
}
if(t.x==PeoplePosition[i].x&&t.y==PeoplePosition[i].y){//如果遇到感染区间,标记一下
flag=1;
}
}
return num;
}
}; 时间复杂度:
空间复杂度:![]()



京公网安备 11010502036488号