编程之美区间重合判断

来源:互联网 发布:下载淘宝app官方软件 编辑:程序博客网 时间:2024/05/17 05:56

一,问题:

    1. 给定一个源区间[x,y]和N个无序的目标区间[x1,y1] [x2,y2] ... [xn,yn],判断源区间[x,y]是不是在目标区间内。

     2. 给定一个窗口区域和系统界面上的N个窗口,判断这个窗口区域是否被已有的窗口覆盖。

方法一:编程之美的解法,首先利用快排将区间按照从小到大排序,[2,3][1,2][3,9]-》[1,2][2,3][3,9];然后对排序的区间进行合并;合并后运用二分法查找。

#include <iostream>#include <algorithm>using namespace std;struct Line{int low,high;Line(int l=0,int h=0):low(l),high(h){}bool operator<(Line & other){return low<other.low;}};const int MAX = 100;Line lines[MAX];//注意咱们搜索的数为刚好小于key的那个值int BinarySearchLower(Line arr[],int len,int target){int low = 0;int high = len-1;while(low < high){int mid = (low + high)/2;if(arr[mid].low>=target)high = mid-1;else low = mid + 1;}return high;}int main(){int n, k, i, j;      cin>>n;  // n是目标区间的个数,k是待查询的源区间的个数  for (i=0; i<n; i++)  cin >> lines[i].low >> lines[i].high;  sort(lines, lines+n);   int cnt = 0; //合并以后的区间数int lasthigh = lines[0].high;          //合并区间for(i=1; i<n; i++){if(lasthigh>=lines[i].low && lasthigh<lines[i].high)lasthigh = lines[i].high;else{lines[cnt].high = lasthigh;lines[++cnt].low = lines[i].low;lasthigh = lines[i].high;}}lines[cnt++].high = lasthigh;Line search = Line(1,6);int sLow = BinarySearchLower(lines,cnt,search.low);int sHigh = BinarySearchLower(lines,cnt,search.high);if(sLow==sHigh && search.high<=lines[sLow].high)//注意要判断cout<<"Yes"<<endl;else cout<<"No"<<endl;system("pause");return 0;}


方法二:并查集

#include <iostream>using namespace std;const int size = 100;int faher[size];//我们用正负区分根节点//负表示根节点,负数表示集合中的个数//正数表示子节点,father[i]表示父亲的索引void MakeSet(int len)//-1表示集合中的个数为1{for(int i=0; i<len; i++){faher[i] = -1;//初识化,大家独自一个集体}}int Find(int x){if(faher[x]>=0)return Find(faher[x]);elsereturn x;}void Union(int x,int y){int xRoot = Find(x);int yRoot = Find(y);int temp;if(xRoot != yRoot){ temp = faher[xRoot] + faher[yRoot];if(faher[xRoot]<faher[yRoot]){//说明x的子节点多余y的子节点,避免生产退化树faher[xRoot] = temp;faher[yRoot] = xRoot;}else{faher[yRoot] = temp;faher[xRoot] = yRoot;}}}void PrintSet(int len){cout<<"Set:";for(int i=0; i<len; i++)cout<<faher[i]<<" ";cout<<endl;}int main(){    int n;cin>>n;  //区间的个数   MakeSet(20);PrintSet(20);while(n--){ int x,y;cin>>x>>y; //输入每个区间   if(x>y){//这一步很关键,表示考虑的周到   swap(x, y);      }  for(int i=x+1; i<=y; i++){//将区间内的 段合并到已有区间   Union(x,i);  }  PrintSet(20);}    int x1, y1;  cin>>x1>>y1;//输入要判断区间  if(Find(x1) == Find(y1)){  cout<<"yes"<<endl;      }  else{  cout<<"no"<<endl;      }  system("pause");  return 0;}

这里贴一道百度的题目:题目描述:请编写程序,找出下面“输入数据及格式”中所描述的输入数据文件中最大重叠区间的大小。对一个正整数n,如果n在数据文件中某行的两个正整数(假设为A和B)之间,即A<=n<=B或A>=n>=B,则n属于该行;如果n同时属于行i和j,则i和j有重叠区间;重叠区间的大小是同时属于行i和j的整数个数。

 例如,行(10 20)和(12 25)的重叠区间为[12 20],其大小为9;行(20 10)和(12 18)的重叠区间为[10 12],其大小为3;行(20 10)和(20 30)的重叠区间大小为1。

答案:解法1先排序+判断重复的区间http://www.cnblogs.com/absolute8511/archive/2009/05/13/1649584.html

                解法2:用位图,int bitmap[len],对将每个区间写入位图,位图相应位置加1操作,bitmap[pos]++,最后统计大于的区域且连续的区域的长度最大值。就向下图所示,区域的计数为1表示有但是没有重叠,0表示该区间没有被覆盖到,2表示有个区间覆盖到,3表示有3个区间覆盖到,4表示有4个区间覆盖到。我们只有判断大于1区域长度的最大值,下图中明显为4区域。

________________________________________________________________________

|______1_____|______2______|____3____|____0____|_______4_________________|

            解法3:线段树。




原创粉丝点击