题目描述
请编写程序,找出下面 “ 输入数据及格式 ” 中所描述的输入数据文件中最大重叠区间的大小。
对一个正整数 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 。
输入数据:程序读入已被命名为 input.txt 的输入数据文本文件,该文件的行数在 1 到 1,000,000 之间,每行有用一个空格分隔的 2 个正整数,这 2 个正整数的大小次序随机,每个数都在 1 和 2^32-1 之间。(为便于调试,您可下载测试 input.txt 文件,实际运行时我们会使用不同内容的输入文件。)
输出数据:在标准输出上打印出输入数据文件中最大重叠区间的大小,如果所有行都没有重叠区间,则输出 0 。
评分标准:程序输出结果必须正确,内存使用必须不超过 256MB ,程序的执行时间越快越好。
算法思路:
采用递推的方式。
先对所有区间以起始端点为基础进行排序,得到一个排序后的区间序列。然后对每一个区间考察后面可能与其重叠的区间。
具体方式为:
设当前的区间为c[a, b], 紧邻的下一个区间为n[a,b].
- 当 c.b < n.a时, n,c没有重叠区间。又由于区间是按照起始点递增排序,所以后续的区间也不会与c有重叠区间。
- 当 c.b >= n.a 时候,n, c有重叠区间。大小为 min{c.b-n.a, n.b-n.a}
- 将得到的当前覆盖长度与保存的max做比较,保存大者。
- 如此对所有的区间都进行这个操作。值得注意的是,当 c.b > n.b时候,n区间被包含在c区间中。在后续的遍历中就无需考虑n这个区间了。小小的技巧在特殊情况下(比如很多区间嵌套),会很快提高运行速度。
代码:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
// find the longest overlap interval
class Interval {
public :
int first;
int last;
public:
Interval(int first, int last);
};
Interval::Interval(int first, int last)
{
this->first = first;
this->last = last;
}
bool intervalCompare(Interval a, Interval b)
{
return a.first < b.first;
}
void swap(int & a, int & b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int max(int a, int b)
{
return a > b? a : b;
}
int min(int a, int b)
{
return a < b? a : b;
}
void print(vector<Interval> * v)
{
vector<Interval>::iterator it;
for (it=v->begin(); it!=v->end(); ++it)
cout << "[" << it->first << "," << it->last<<"]\t";
cout << endl;
}
int main()
{
ifstream in("c:/input.txt");
vector<Interval> * allIntervals = new vector<Interval>();
vector<Interval>::iterator it;
int first;
int last;
while(in >> first >> last)
{
if(first > last)
swap(first, last);
Interval *a = new Interval(first, last);
allIntervals->push_back(*a);
}
cout << "input is : " << endl;
print(allIntervals);
sort(allIntervals->begin(), allIntervals->end(), intervalCompare);
cout << "after sorted, is : " << endl;
print(allIntervals);
//find the longest overlap
//µ±Ç°µÄinterval c[a,b],½ô½ÓÆäºóµÄinterva n[a,b]
//µ± c.b < n.a ʱ£¬Çø¼äûÓи²¸Ç
//µ± c.b >= n.a ʱ£¬µ±Ç°µÄÇø¼ä¸²¸ÇΪ max(c.b-n.a, n.b-n.a).
int maxOverlapLength = 0;
int length = allIntervals->size();
for(int i = 0; i < length-1; i++)
{
Interval cur = (*allIntervals)[i];
int j = i+1;
Interval next = (*allIntervals)[j];
while(cur.last >= next.first)
{
int m = min(cur.last-next.first, next.last-next.first);
maxOverlapLength = max(m, maxOverlapLength);
j = j+1;
next = (*allIntervals)[j];
if(cur.last >= next.last)
{
i++;
}
}
}
cout << "max overlap length is : " << maxOverlapLength << endl;
system("pause");
return 0;
}
讨论: