区间重合判断

方法一

1 对N个无序的目标区间进行排序

2 顺序判断源区间是否在目标区间内

bool isOverlap([x, y], [x1, y1][x2,y2]...[xn,yn])

{

         //以x为key进行升序排序,排序后x1<=x2<=x3<=..<=xn

         sort([x1,y1][x2,y2]...[xn,yn]);

         flg=0;

         lastEnd=x1;

         for (i=1;i<=n; i++)

         {

                   if(flg==0)

                   {

                            //进入包含源区间的低端的目标区间

                            if(xi<=x && yi>=x)

                            {

                                     flg = 1;

                                     lastEnd= max(lastEnd, yi);

                            }

                   }

                   else

                   {

                            //判断区间是否中断

                            if(xi > lastEnd)

                                     break;

                            lastEnd= max(lastEnd, yi);

                            //判断是否是源区间高端所在的目标区间

                            if(xi<=y && yi>=y)

                            {

                                     flg = 2;

                                     break;

                            }

                           

                   }

        }

return (flg == 2);

}

         时间复杂度:排序O(nlogn)+ 遍历O(n)

 

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

/*
	输入:
	3 5        //第一行两个整数表示源区间
	5          //第二行一个整数表示目标区间个数n
	1 2       //接下来n行表示目标区间
	2 3
	3 5
	6 7
	7 8
	输出:
	true or false
*/
typedef struct  _elemType {
	int x, y;
}ElemType;

#define  N   50   //最大区间数
#define LEN 100 //区间最大长度
#define MAX(a, b) ((a)>=(b)?(a):(b))

int comFun(const void *a, const void *b)
{
	const ElemType *p1 = static_cast<const ElemType *>(a);
	const ElemType *p2 = static_cast<const ElemType *>(b);
	return (p1->x - p2->x);
}

bool isOverlap(int x, int y, const ElemType *p, int n)
{
	int flg=0;
	int lastEnd=p[0].y;

	for (int i=0; i<n; i++)
	{
		if (flg == 0)
		{
			//找到包含源区间低端的目标区间
			if (x>=p[i].x && x <=p[i].y)
			{
				flg = 1;
				lastEnd = MAX(lastEnd, p[i].y);
			}
		}
		else
		{
			//判断区间是否中断
			if (p[i].x > lastEnd)
				break;
			lastEnd = MAX(lastEnd, p[i].y);
			//if (y>=p[i].x && y<=p[i].y)
			//if (y<=p[i].y)  
			if (y<=lastEnd)
			{
				flg = 2;
				break;
			}
		}
	}
	return (flg == 2);
}

void main()
{
	int x, y;
	while(scanf("%d%d", &x ,&y) != EOF)
	{
		int n;
		scanf("%d", &n);
		ElemType des[N];
		int i=0;
		while (i<n)
		{
			scanf("%d%d", &des[i].x, &des[i].y);
			i++;
		}
		qsort(des, n, sizeof(ElemType), comFun);
		//test qort
		/*printf("\n");
		for (i=0; i<n; i++)
			printf("%d %d\n", des[i].x, des[i].y);
		*/
		bool ret = isOverlap(x, y, des, n);
		printf("%s\n", ret?"true":"false");
	}
}

方法二

空间换时间

假设区间的最大长度为n,用一个int数组A[n]来表示区间,A[i] (1<=i<=n)表示区间,即区间[i, i+1]上长度为1的一个子区间,如果A[i]为零表示该子区间不包含在目标区间中,否则A[i]包含在目标区间中。更好的表达是:把N个无序的目标区间逐个投影到坐标轴上,然后遍历元区间所在的坐标轴部分,如果全为1表示,源区间包含在目标区间中。

bool isOverlap([x, y], [x1, y1][x2,y2]...[xn,yn])

{

         int A[n] = {0};

         for (i=1;i<=n; i++)

         {

                   A[xi– yi] = 1;

         }

         for (i=x;i<=y; i++)

                   if(A[i]==0)

                            return0;

         return 1;

}

时间复杂度O(n) 空间复杂度O(n)

#include <stdio.h>

/*
	输入:
	3 5        //第一行两个整数表示源区间
	5          //第二行一个整数表示目标区间个数n
	1 2       //接下来n行表示目标区间
	2 3
	3 5
	6 7
	7 8
	输出:
	true or false
*/
typedef struct  _elemType {
	int x, y;
}ElemType;

#define  N   50   //最大区间数
#define LEN 100 //区间最大长度

bool isOverlap(int x, int y, const ElemType *p, int n)
{
	int A[LEN] = {0};
	int i;
	for (i=0; i<n; i++)
	{
		for (int j=p[i].x; j<p[i].y; j++)
			A[j] = 1;
	}
	for (i=x; i<=y; i++)
		if (A[i] == 0)
			return 0;
	return 1;
}

void main()
{
	int x, y;
	while(scanf("%d%d", &x ,&y) != EOF)
	{
		int n;
		scanf("%d", &n);
		ElemType des[N];
		int i=0;
		while (i<n)
		{
			scanf("%d%d", &des[i].x, &des[i].y);
			i++;
		}
		
		bool ret = isOverlap(x, y, des, n);
		printf("%s\n", ret?"true":"false");
	}
}

 

方法三

把方法二中的int数组换成位图,一个位表示一个单位长度为1的子区间,进一步降低空间复杂度

bool isOverlap([x, y], [x1, y1][x2,y2]...[xn,yn])

{

         int A[(n+31)/32]= {0};

         for (i=1;i<=n; i++)

         {

                   A[xi– yi] = 1;

         }

         for (i=x;i<=y; i++)

                   if(A[i]==0)

                            return0;

         return 1;

}

时间复杂度O(n) 空间复杂度O(n)

 

#include <stdio.h>

/*
	输入:
	3 5        //第一行两个整数表示源区间
	5          //第二行一个整数表示目标区间个数n
	1 2       //接下来n行表示目标区间
	2 3
	3 5
	6 7
	7 8
	输出:
	true or false
*/
typedef struct  _elemType {
	int x, y;
}ElemType;

#define  N   50   //最大区间数
#define LEN 100 //区间最大长度
#define  BITMASK 32
#define set_bit(a, n) (a[n/BITMASK] |= (1 << n%BITMASK))
#define read_bit(a, n) (a[n/BITMASK] & (1<<n%BITMASK))

bool isOverlap(int x, int y, const ElemType *p, int n)
{
	int A[(LEN+31)/32] = {0};
	int i;
	for (i=0; i<n; i++)
	{
		for (int j=p[i].x; j<p[i].y; j++)
			set_bit(A, j);
	}
	for (i=x; i<=y; i++)
		if (read_bit(A, i) == 0)
			return 0;
	return 1;
}

void main()
{
	int x, y;
	while(scanf("%d%d", &x ,&y) != EOF)
	{
		int n;
		scanf("%d", &n);
		ElemType des[N];
		int i=0;
		while (i<n)
		{
			scanf("%d%d", &des[i].x, &des[i].y);
			i++;
		}
		
		bool ret = isOverlap(x, y, des, n);
		printf("%s\n", ret?"true":"false");
	}
}

方法四

用目标区间来消减源区间,遍历完目标区间,如果把源区间消减完,则源区间在目标区间内。比较麻烦的一点是,可能会把源区间分成多个区间。

为方便出来,可以用链表来表示源区间,这样分离出一个区间就添加一个节点,如果某个区间被消减了,就删除相应的节点。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
	输入:
	3 5        //第一行两个整数表示源区间
	5          //第二行一个整数表示目标区间个数n
	1 2       //接下来n行表示目标区间
	2 3
	3 5
	6 7
	7 8
	输出:
	true or false
*/
typedef struct  _elemType {
	int x, y;
}ElemType;

#define  N   50   //最大区间数
#define LEN 100 //区间最大长度



bool isOverlap(int x, int y, const ElemType *p, int n)
{
	typedef struct _tempType {
		ElemType region;
		struct _tempType *next;
	}TempType;
	TempType *head = (TempType *)malloc(sizeof(TempType));
	TempType *q, *t, *pre;
	head->region.x = x;
	head->region.y = y;
	head->next = NULL;

	int i;
	for (i=0; i<n; i++)
	{
		q = head, t=NULL, pre=head;
		while (q)
		{
			//目标区间在源区间的中间  --> 分割区间
			if (p[i].x > q->region.x && p[i].y < q->region.y)
			{
				t = (TempType *)malloc(sizeof(TempType));
				t->region.x = q->region.x;
				t->region.y = p[i].x;
				q->region.x = p[i].y;
				t->next = head;
				head = t;
			}
			//目标区间在源区间之外
			else if (p[i].y <= q->region.x || p[i].x >= q->region.y)
			{
				; //nothing tobe done
			}
			else 
			{
				//分割左边
				if (p[i].y <= q->region.y)
					q->region.x = p[i].y;
				else
					q->region.y = p[i].x;
			}
			t = NULL;
			if (q->region.x >= q->region.y)
			{
				t = q;
			}
			
			if (t)
			{
				q = q->next;
				free(t);
				if (t == head)
				{					
					head = NULL;
				}
				else
				{
					pre->next = q;
				}
			}
			else
			{
				pre = q;
				q = q->next;
			}
		}
		if (head == NULL)
			return 1;
	}
	t = head;
	while (t)
	{
		TempType *temp = t;
		t = t->next;
		free(temp);
	}
	return (head == NULL);

}

void main()
{
	int x, y;
	while(scanf("%d%d", &x ,&y) != EOF)
	{
		int n;
		scanf("%d", &n);
		ElemType des[N];
		int i=0;
		while (i<n)
		{
			scanf("%d%d", &des[i].x, &des[i].y);
			i++;
		}
		
		bool ret = isOverlap(x, y, des, n);
		printf("%s\n", ret?"true":"false");
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值