Merge Intervals

Given a collection of intervals, merge all overlapping intervals.

For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].

» Solve this problem


区间合并 和 求最长区间 一样,关键在于如何记录区间信息,能够降低复杂度。


最简单的思路是用一个bool数组,记录区间中的每一位是否被覆盖。

例如:

intervals: [1, 4] [8, 9] [20, 30] [7, 14] [2, 9]

设一个数组 bool f[30],初始化全部为false

[1, 4]就把f[1]..f[4]全部置为true

其他区间一次类推,最后扫描f数组,就能得到区间合并的结果。

这种做法对于小数据还行,大数据会超市。


这样做,存在很多重复工作,例如[1, 4] [8, 9] [7, 14] [2, 9]这四个区间,会反复将f[2] f[3] f[4][ f[5] f[6] f[7] f[8] f[9]设为true。

所以,我们需要考虑的是如何去除重复的工作。实际上,两个端点就能描述出一个区间,关键在于如何标记出两个端点,让我们在扫描时能够知道这个区间被覆盖。


一个很巧妙的做法就是进入一个区间就加1,出一个区间就减1,如果数值大于0,说明当前处于一个区间中。

还是以刚刚的intervals为例。

设数组 int l[30], r[30],初始化全部为0 

[1, 4]:l[1]++, r[4]--

[8, 9]:l[8]++, r[9]--

...

扫描时,用一个count记录,每次:

count += l[i],如果count>0说明i处于一个区间中

count -= r[i],如果count==0说明i是一个区间的尾端点



  1. /** 
  2.  * Definition for an interval. 
  3.  * struct Interval { 
  4.  *     int start; 
  5.  *     int end; 
  6.  *     Interval() : start(0), end(0) {} 
  7.  *     Interval(int s, int e) : start(s), end(e) {} 
  8.  * }; 
  9.  */  
  10. class Solution {  
  11. public:  
  12.     vector<Interval> merge(vector<Interval> &intervals) {  
  13.         // Start typing your C/C++ solution below  
  14.         // DO NOT write int main() function  
  15.         vector<Interval> answer;  
  16.         if (intervals.empty()) {  
  17.             return answer;  
  18.         }  
  19.   
  20.         int min = 1000000, max = -1000000;  
  21.         for (vector<Interval>::iterator iter = intervals.begin(); iter != intervals.end(); iter++) {  
  22.             min = min < iter->start ? min : iter->start;  
  23.             max = max > iter->end ? max : iter->end;  
  24.         }  
  25.           
  26.         int left[max - min + 1];  
  27.         int right[max - min + 1];  
  28.         memset(left, 0, sizeof(int) * (max - min + 1));  
  29.         memset(right, 0, sizeof(int) * (max - min + 1));  
  30.         for (vector<Interval>::iterator iter = intervals.begin(); iter != intervals.end(); iter++) {  
  31.             left[iter->start - min]++;  
  32.             right[iter->end - min]++;  
  33.         }  
  34.           
  35.         int start = -1, count = 0;  
  36.         for (int i = 0; i < max - min + 1; i++) {  
  37.             count += left[i];  
  38.             if (count > 0 && start == -1) {  
  39.                 start = i;  
  40.             }  
  41.             count -= right[i];  
  42.             if (count == 0 && start != -1) {  
  43.                 answer.push_back(Interval(start + min, i + min));  
  44.                 start = -1;  
  45.             }  
  46.         }  
  47.           
  48.         return answer;  
  49.     }  

  50. };  

  51. 如果要在Vector容器中存放结构体类型的变量,经常见到两种存放方式.
  52. 方式一:放入这个结构体类型变量的副本。

    方式二:放入指向这个结构体类型变量的指针。

    假设结构体类型变量是这样的,

    1. typedef struct student{  
    2.    char school_name[100];  
    3.    char gender;  
    4.    int age;  
    5.    bool is_absent;  
    6. } StudentInfo;  

    那么,方式一和方式二的实现分别如下所示:

    1. /*[方式一] 结构体放栈中,vector中放副本---------------------*/  
    2. #include <iostream>  
    3. #include <string>  
    4. #include <vector>  
    5. typedef struct student{  
    6.    char school_name[100];  
    7.    char gender;  
    8.    int age;  
    9.    bool is_absent;  
    10. } StudentInfo;  
    11.    
    12. typedefstd::vector<StudentInfo> StudentInfoVec;  
    13.   
    14. void print(StudentInfoVec* stduentinfovec){  
    15.    for (int j=0;j<(*stduentinfovec).size();j++)  
    16.     {  
    17.        std::cout<<  
    18.            (*stduentinfovec)[j].school_name<<"\t"<<  
    19.            (*stduentinfovec)[j].gender<<"\t"<<  
    20.            (*stduentinfovec)[j].age<<"\t"<<  
    21.            (*stduentinfovec)[j].is_absent<<"\t"<<std::endl;  
    22.     }  
    23.    return;  
    24. }  
    25.    
    26. int main(){  
    27.    StudentInfo micheal={"Micheal",'m',18,false};  
    28.    StudentInfo cherry={"Cherry",'f',16,true};  
    29.    StudentInfoVec studentinfovec;  
    30.    studentinfovec.push_back(micheal);  
    31.    studentinfovec.push_back(cherry);  
    32.    print(&studentinfovec);  
    33.    return 0;  
    34. }  
    方式一的输出结果

    1. /*[方式二]  结构体放入堆中,vector中放指针---------------------*/  
    2. typedef struct student{  
    3.    char* school_name;  
    4.    char gender;  
    5.    int age;  
    6.    bool is_absent;  
    7. } StudentInfo;  
    8.    
    9. typedefstd::vector<StudentInfo*> StudentInfoPtrVec;  
    10.   
    11. void print(StudentInfoPtrVec*stduentinfoptrvec){  
    12.    for (int j=0;j<(*stduentinfoptrvec).size();j++)  
    13.     {  
    14.        std::cout<<  
    15.            (*stduentinfoptrvec)[j]->school_name<<"\t"<<  
    16.            (*stduentinfoptrvec)[j]->gender<<"\t"<<  
    17.            (*stduentinfoptrvec)[j]->age<<"\t"<<  
    18.            (*stduentinfoptrvec)[j]->is_absent<<"\t"<<std::endl;  
    19.     }  
    20.    return;  
    21. }  
    22.   
    23. int main(){  
    24.    
    25.    StudentInfoPtrVec studentinfoptrvec;  
    26.    
    27.    char* p_char_1=NULL;  
    28.    p_char_1=new char[100];  
    29.    strcpy(p_char_1,"Micheal");  
    30.    StudentInfo* p_student_1=new StudentInfo;  
    31.    p_student_1->school_name=p_char_1;  
    32.    p_student_1->gender='m';  
    33.    p_student_1->age=18;  
    34.    p_student_1->is_absent=false;  
    35.    studentinfoptrvec.push_back(p_student_1);  
    36.    
    37.    char* p_char_2=NULL;  
    38.    p_char_2=new char[100];  
    39.    strcpy(p_char_2,"Cherry");  
    40.    StudentInfo* p_student_2=new StudentInfo;  
    41.     p_student_2->school_name=p_char_2;  
    42.    p_student_2->gender='f';  
    43.    p_student_2->age=16;  
    44.    p_student_2->is_absent=false;  
    45.    studentinfoptrvec.push_back(p_student_2);  
    46.         
    47.    print(&studentinfoptrvec);  
    48.    delete p_char_1;  
    49.    delete p_student_1;  
    50.    delete p_char_2;  
    51.    delete p_student_2;  
    52.    return 0;  
    53.    
    54. }  


    方式二的输出结果,同上,依然是



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值