每天一到算法题--重叠区间大小

来源:互联网 发布:python 调用c dll 编辑:程序博客网 时间:2024/05/17 23:52

题目描述

请编写程序,找出下面 “ 输入数据及格式 ” 中所描述的输入数据文件中最大重叠区间的大小。

对一个正整数 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 intervalclass 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;}

讨论:

这里采用的方式是将所有数据读入内存,此时,很有可能会有内存益处的情况。此时可以先遍历一边,将区间分成两部分/四部分,每一部分按照上面的方法给出最大重叠区间。然后在考虑跨越两个部分的边界情况。综合得到结果。


原创粉丝点击