现在的位置: 首页 > 综合 > 正文

[各种面试题] 区间相交

2018年04月12日 ⁄ 综合 ⁄ 共 2219字 ⁄ 字号 评论关闭

n个左右端点都为整数的区间,判断每个区间是否有与其它某个区间相交(区间端点重合也算相交)。


第一个反应是线段树,先留一下,写个排序遍历的:

/*
struct Interval {
    int start;   //区间左端点
    int end;   //区间右端点
};
*/

struct IntervalWithPos
{
	Interval in;
	int pos;
	IntervalWithPos(Interval i,int p):in(i),pos(p){}
	bool operator<(const IntervalWithPos& oth)const
	{
		if ( in.start == oth.in.start )
			return in.end<oth.in.end;
		return in.start<oth.in.start;
	}
};
// intervals包含n个区间
// 结果存放到isIntersected中(已分配空间,不需要push_back)
// isIntersected[i]表示第i个区间是否与其它区间相交
void intersected(vector<Interval> &intervals, vector<bool> &isIntersected) {
	int n =intervals.size();
	if ( n== 0 )
		return;
	typedef IntervalWithPos IPos;
	vector<IPos> inters;
	inters.reserve(n);
	for(int i=0;i<n;i++)
		inters.push_back(IPos(intervals[i],i));
	sort(inters.begin(),inters.end());
	int end=inters[0].in.end;
	for(int i=1;i<n;i++)
	{
		if ( end >= inters[i].in.start)
			isIntersected[inters[i].pos]=true;
		end=max(end,inters[i].in.end);
	}
	int start=inters[n-1].in.start;
	for(int i=n-2;i>=0;i--)
	{
		if ( start <=inters[i].in.end )
			isIntersected[inters[i].pos]=true;
		start=min(start,inters[i].in.start);
	}
}

线段树确实还是不熟悉啊,昨天树里的每个节点保存什么,怎么更新想了半天,后来想到跟区间加和是一样的道理,每次加1而已。

const int MAXN= 10;
int cover[MAXN<<2];
int add[MAXN<<2];
void build(int rt)
{
	memset(cover,0,sizeof(cover));
	memset(add,0,sizeof(add));
}
void pushDown(int rt)
{
	if ( add[rt]!= 0 )
	{
		add[rt<<1]+=cover[rt];
		add[rt<<1|1]+=cover[rt];
		cover[rt<<1]+=add[rt];
		cover[rt<<1|1]+=add[rt];
		add[rt]=0;
	}
}
void pushUp(int rt)
{
	cover[rt]=max(cover[rt<<1],cover[rt<<1|1]);
}
void insert(int rt,int l,int r,int L,int R)
{
	if ( L<=l && r <=R )
	{
		add[rt]++;
		cover[rt]++;
		return;
	}
	pushDown(rt);
	int mid=(l+r)>>1;
	if ( L<=mid )
		insert(rt<<1,l,mid,L,R);
	if ( R>mid )
		insert(rt<<1|1,mid+1,r,L,R);
	pushUp(rt);
}
int query(int rt,int l,int r,int L,int R)
{
	if (L<=l&&r<=R)
	{
		return cover[rt];
	}
	pushDown(rt);
	int mid=(l+r)>>1;
	int left=0,right=0;
	if (L<=mid )
		left=query(rt<<1,l,mid,L,R);
	if ( R>mid )
		right=query(rt<<1|1,mid+1,r,L,R);
	pushUp(rt);
	return max(left,right);
}

struct Interval {
    int start;   //区间左端点
    int end;   //区间右端点
};


// intervals包含n个区间
// 结果存放到isIntersected中(已分配空间,不需要push_back)
// isIntersected[i]表示第i个区间是否与其它区间相交
void intersected(vector<Interval> &intervals, vector<bool> &isIntersected) {
	int n=intervals.size();
	if (n<=1 )
		return ;
	build(1);
	for(int i=0;i<n;i++)
		insert(1,0,MAXN,intervals[i].start,intervals[i].end);
	for(int i=0;i<n;i++)
	{
		int k = query(1,0,MAXN,intervals[i].start,intervals[i].end);
		if ( k>1 )
			isIntersected[i]=true;
	}
}

抱歉!评论已关闭.