给定一个源区间【x,y】(y>=x) 和N个 无序的目标区间[x1,y1] [x2,y2] ....[xn,yn] 判断源区间[x,y]是不是在目标区间内
方法1:
一个直接的思路即将源区间[x,y]和N个无序的目标区间逐个投影到坐标轴上 只考察源区间未被覆盖的部分 如果所有的目标区间全部投影完毕 仍有源区间没有被覆盖 那么源区间就不在目标区间之间
方法2:
对现有的数组进行一些预处理(如合并 排序) 将无序的目标区间合并成几个有序的区间 这样就可以进行区间的比较
首先可以做一次数据初始化的工作由于目标区间是无序的 可以对其进行合并操作 使其变得有序 先将目标区间数组按X轴坐标从小到大排序 然后扫描数组 将这些区间合并成诺干个不相交的区间 因为区间下标 按照升序排列 运用二分查找的方法 来判断源区间[x y]是否被合并后的这些互不相交的区间的某一个包含
排序的时间复杂度为:O(N*logN) (N为目标区间个数)
合并的时间复杂度为O(N)
单次查找的时间复杂度为O(log2N)
总的时间复杂度为 O (NlogN +k*logN) k为查询的次数 合并目标区间数组的初始化数据操作只需要进行一次
typedef struct point{
int x;
int y;
};
int cmp( const void *a , const void *b )
{
return (*(point *)a).x>(*(point *)b).x?1:-1;
}
void merges(point *p,int n,point *d,int *k)
{
int *t=new int[2*n];
for(int i=0;i<n;i++)
{
t[2*i]=p[i].x;
t[2*i+1]=p[i].y;
}
int flag=0;
for(int i=0,j=i+2;i<2*n-flag;i=i+2)
{
int tmp=i+1;
j=tmp+1;
while(1)
{
if(t[tmp]>=t[j])
{
t[tmp]=t[j]=-1;
flag=flag+2;
tmp=tmp-1;
j=j+1;
}
else
break;
}
}
int tt=0;
for(int i=0;i<2*n;)
{
if(t[i]!=-1 )
d[tt].x=t[i];
i++;
while( t[i]==-1)
i++;
d[tt].y=t[i];
i++;
(tt)++;
}
*k=tt;
delete []t;
}
int find(point *p,int k,int m)
{
int l=0,r=k;
while (l<=r)
{
int mid=(l+r)>>1;
if( m >= p[mid].x)
l=mid+1;
else
r=mid-1;
}
return r;
}
int main() {
int n=4;
int *a=new int [n];//对应 x1, x2, ... , xn
int *b=new int [n];//对应 y1, y2, ... ,yn
point *p1=new point[n];
point *p2=new point[n];
a[0]=1;
a[1]=5;
a[2]=2;
a[3]=10;
b[0]=3;
b[1]=9;
b[2]=4;
b[3]=11;
p1[0].x=1;
p1[1].x=5;
p1[2].x=2;
p1[3].x=8;
p1[0].y=3;
p1[1].y=9;
p1[2].y=4;
p1[3].y=11;
int x=2;
int y=10;
qsort(p1,4,sizeof(p1[0]),cmp);
int k=0;
merges(p1,n,p2,&k);
int s1= find(p2,k,x);
int s2=find(p2,k,y);
if(s1==s2 )
cout<<"true"<<endl;
else
cout<<"false"<<endl;
delete []a;
delete []b;
delete[]p1;
delete []p2;
return 0;
}