《编程之美》第2.19节:区间重合判断
问题:给定一个源区间[x,y](y>=x)和N个无序的目标区间[x1,y1]…[xn,yn],判断源区间[x,y]是不是在目标区间内?
解法:将目标区间排序,然后合并重合区间,最后用二分法查看源区间是否在目标区间内。
代码:
<span style="font-size:14px;">#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
struct Node
{
int begin;
int end;
Node(int b=0,int e=0):begin(b),end(e){}
bool operator<(const Node &node)const
{return begin==node.begin?end<node.end:begin<node.begin;}
};
bool segmentIncluded(list<Node> L,const Node &node)
{
L.sort();
list<Node>::iterator iter=L.begin();
list<Node>::iterator temp=L.begin();
for(++iter;iter!=L.end();)
{
if(temp->end>=iter->begin)
{
temp->end=iter->end;
iter=L.erase(iter);
}
else
{
temp=iter;
++iter;
}
}
for(iter=L.begin();iter!=L.end();++iter)
{
if(iter->begin<=node.begin && iter->end>=node.end)
return true;
}
return false;
}
int main()
{
list<Node> L;
L.push_back(Node(2,3));
L.push_back(Node(1,2));
L.push_back(Node(3,9));
bool result=segmentIncluded(L,Node(1,6));
cout<<result<<endl;
system("pause");
return 0;
}</span>
一下转自:http://blog.youkuaiyun.com/tianshuai1111/article/details/7828961解法比较巧妙
先用区间的左边界值对目标区间进行排序O(nlogn),对排好序的区间进行合并O(n),对每次待查找的源区间,用二分查出其左右两边界点分别处于合并后的哪个源区间中O(logn),若属于同一个源区间则说明其在目标区间中,否则就说明不在。
注意:下面这个代码GetIndex函数查找的是小于key的与key最接近的下标值,先找出与源区间[low,high]中low最接近的起始点,然后找到与high最接近的起始点,这两个起始点应该是一个点,否则[low,high]区间就不在目标区间内。
- #include <iostream>
- #include <algorithm>
- using namespace std;
- struct Line
- {
- int low, high;
- bool operator<(const Line &l) const
- {return low<l.low;}
- };
- #define MAXN 10001
- Line lines[MAXN]; // 目标区间
- int ncnt = 0; // 合并后区间的个数
- #define N 101
- Line sl[N]; // 待查询的源区间
- // 用二分查找找出key所在的区间,以区间的low作为划分
- int GetIndex(int key)
- {
- int u, v;
- u = 0; v = ncnt-1;
- while (u<=v) // u,v可取等号
- {
- int m = (u+v)>>1;
- if (key >= lines[m].low)
- u = m+1;
- else
- v = m-1;
- }
- return v;
- }
- int main()
- {
- int n, k, i, j;
- cin >> n >> k; // n是目标区间的个数,k是待查询的源区间的个数
- for (i=0; i<n; i++)
- cin >> lines[i].low >> lines[i].high;
- for (i=0; i<k; i++)
- cin >> sl[i].low >> sl[i].high;
- // 排序O(nlogn)
- sort(lines, lines+n);
- // 合并O(n)
- int lasthigh = lines[0].high;
- for (i=1; i<n; i++)
- if (lasthigh >= lines[i].low)
- lasthigh = lines[i].high;
- else
- {
- lines[ncnt++].high = lasthigh;
- lines[ncnt].low = lines[i].low;
- lasthigh = lines[i].high;
- }
- lines[ncnt++].high = lasthigh;
- for (i=0; i<k; i++)
- {
- // 单词查找时间O(logn)
- int s1 = GetIndex(sl[i].low);
- int s2 = GetIndex(sl[i].high);
- if (s1==s2 && sl[i].high <= lines[s2].high)
- printf("Yes\n");
- else
- printf("No\n");
- }
- }