区间重合判断

题目:给定一些无序区间,判断某个给定的特定区间是否在这些无序的区间内。
这个题目比较简单,首先将给定的区间排序,在对重合的区间进行排序,使得区间变成递增且不重叠的若干个区间,对于给定的区间在已经处理好的区间内进行二分查找,完成区间覆盖的判断。
程序如下:

[cpp] view plaincopy

  1. #include <stdio.h>  
  2. #include <vector>  
  3. #include <algorithm>  
  4. class Interval {  
  5.  public:  
  6.   Interval(int start, int end) : start_(start), end_(end) {}  
  7.   Interval() :start_(0), end_(0) {}  
  8.   static bool OrderByStart(const Interval& left, const Interval& right) {  
  9.     return left.start_ < right.start_;  
  10. 10.   }  
  11. 11.   friend bool operator<(const Interval& left, const Interval& right) {  
  12. 12.     return left.start_ < right.start_;  
  13. 13.   }  
  14. 14.   int start_;  
  15. 15.   int end_;  

16. };  

17. void CombinInterval(std::vector<Interval>& orginal, std::vector<Interval>* combined) {  

  1. 18.   if (orginal.size() < 1) {  
  2. 19.     return;  
  3. 20.   }  
  4. 21.   sort(orginal.begin(), orginal.end(), Interval::OrderByStart);  
  5. 22.   Interval combined_interval = orginal[0];  
  6. 23.   int new_ending = orginal[0].end_;  
  7. 24.   for (int i = 1; i < orginal.size(); ++i) {  
  8. 25.     if (combined_interval.end_ >= orginal[i].start_) {  
  9. 26.       new_ending = combined_interval.end_ > orginal[i].end_ ? combined_interval.end_ : orginal[i].end_;  
  10. 27.       continue;  
  11. 28.     }  
  12. 29.     combined_interval.end_ = new_ending;  
  13. 30.     combined->push_back(combined_interval);  
  14. 31.     combined_interval = orginal[i];  
  15. 32.     new_ending = orginal[i].end_;  
  16. 33.   }  
  17. 34.   combined_interval.end_ = new_ending;  
  18. 35.   combined->push_back(combined_interval);  

36. }  

37. bool CoverTest(const Interval& interval, std::vector<Interval>& intervals, Interval* covered_interval) {  

  1. 38.   std::vector<Interval> combined_intervals;  
  2. 39.   CombinInterval(intervals, &combined_intervals);  
  3. 40.   for (int i = 0; i < combined_intervals.size(); ++i) {  
  4. 41.     printf("%d-%d\n", combined_intervals[i].start_, combined_intervals[i].end_);  
  5. 42.   }  
  6. 43.     
  7. 44.   if (combined_intervals.size() < 1) {  
  8. 45.     return false;  
  9. 46.   }  
  10. 47.   int start = 0;  
  11. 48.   int end = combined_intervals.size() -1;  
  12. 49.   int middle = 0;  
  13. 50.   bool found = false;  
  14. 51.   while (end >= start) {  
  15. 52.     middle = (start + end) / 2;  
  16. 53.     if (interval < combined_intervals[middle]) {  
  17. 54.       end = middle - 1;  
  18. 55.     } else if (combined_intervals[middle] < interval) {  
  19. 56.       start = middle + 1;  
  20. 57.     } else {  
  21. 58.       found = true;  
  22. 59.       break;        
  23. 60.     }  
  24. 61.   }  
  25. 62.   int target_index = found ? middle : start - 1;  
  26. 63.   printf("target:%d\n", target_index);  
  27. 64.   if (target_index >= 0 &&  
  28. 65.       combined_intervals[target_index].start_ <= interval.start_ &&  
  29. 66.       combined_intervals[target_index].end_  >= interval.end_) {  
  30. 67.     *covered_interval = combined_intervals[target_index];  
  31. 68.     return true;  
  32. 69.   } else {  
  33. 70.     return false;  
  34. 71.   }  

72. }    

73. int main(int argc, char** argv) {  

  1. 74.   std::vector<Interval> intervals;  
  2. 75.   intervals.push_back(Interval(2,5));  
  3. 76.   intervals.push_back(Interval(3,4));  
  4. 77.   intervals.push_back(Interval(4,7));  
  5. 78.   intervals.push_back(Interval(9,13));  
  6. 79.   Interval target_interval(3, 4);  
  7. 80.   Interval covered_interval;  
  8. 81.   if (CoverTest(target_interval, intervals, &covered_interval)) {  
  9. 82.     printf("the covered interval is (%d, %d)\n", covered_interval.start_, covered_interval.end_);  
  10. 83.   } else {  
  11. 84.     printf("uncovered\n");  
  12. 85.   }  

86. }  

 

程序编写时开始犯了几个错误:

1、函数参数开始使用了const 修饰,导致sort时出错

2、区间合并时,没有将最后一个加入到向量中,new_ending设置的初值也要注意,开始就出错了

3、二分查找,找下界时,需要将查找过程走几遍就比较清楚了,下界是start-1,但如果start为0,下界可能是负数,要注意处理。另外循环条件是start <=end,等号也很重要,如果判断过程中只有一个元素时,就是等号覆盖的情况。

 

 

题目大意:

输入两个表示区间范围的整数[x,y]

然后输入N个无序区间[x1,y1], [x2, y2], [x3, y3]...

求解第一次输入的区间是否在N个无序区间组合成的大区间中。

 

法一:使用并查集,对每个区间合并到一个子树上,最后判断源区间的x和y的根是否相同。

View Code

 

#include<iostream>

using namespace std;

 

const int size = 100;

int father[size];

int rank[size];

 

void make_set(int n)

{

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

        father[i] = i;   

        rank[i] = 1;

    }   

}

 

int find_set(int x)

{

    if(x != father[x]){

        father[x] = find_set(father[x]);   

    }   

    return father[x];

}

 

void Union(int x, int y)

{

    x = find_set(x);   

    y = find_set(y);

    if(x == y){

        return ;   

    }

    if(rank[x] < rank[y]){

        father[x] = y;   

    }

    else{

        father[y] = x;

        if(rank[x] == rank[y]){

            rank[x] ++;   

        }   

    }

}

 

int main()

{

    int x1, y1;

    cin >> x1 >> y1;

    int x, y;

    int n;

    cin >> n;

    make_set(size);

    while(n --){

        cin >> x >> y;

        if(x > y){

            swap(x, y);   

        }

        for(int i = x + 1; i <= y; i ++){

            Union(x, i);

        }

    }   

    if(find_set(x1) == find_set(y1)){

        cout << "yes" << endl;   

    }

    else{

        cout << "no" << endl;   

    }

    system("pause");

}

 

法二:将无序的目标区间排序后,再合并成几个有序的区间,然后把源区间和有序的目标区间比较。

View Code

 

#include<iostream>

#include<vector>

using namespace std;

 

typedef pair<int, int> section;

 

bool cmp(section a, section b)

{

    return a.first < b.first;   

}

 

int main()

{

    section src, tmp;

    cin >> src.first >> src.second;

   

    vector<section> v;

    while(cin >> tmp.first >> tmp.second, tmp.first | tmp.second){

        v.push_back(tmp);   

    }

   

    sort(v.begin(), v.end(), cmp);

   

    vector<section> res;

    vector<section>::iterator it = v.begin();

    int begin = it->first;

    for(; (it + 1) != v.end(); it ++){

        if(it->second < (it + 1)->first){

            res.push_back(make_pair(begin, it->second));   

            begin = (it + 1)->first;

        }   

    }

   

    bool solve = false;

    it = res.begin();

    for(; it != res.end(); it ++){

        if(src.first >= it->first && src.second <= it->second){

            solve = true;   

            break;

        }   

    }

    if(solve){

        cout << "in" << endl;   

    }

    else{

        cout << "out" << endl;   

    }

    system("pause");

}

 

posted @ 2013-06-25 16:47  夜雨阑珊  阅读(1122)  评论(0编辑  收藏  举报