题意:
给定多个区间和一个受感染的区间,问与受感染区间相交集的总个数。
(相交包含直接相交和间接相交)
方法一:
并查集(超时)
思路:这道题的核心是找 包含受感染区间 的最大连续区间的个数。利用并查集,将这些区间分割成多块不相交的集合,找到包含受感染区间的那个集合,并返回那个集合中的节点数量。
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; } };
时间复杂度:空间复杂度: