leetcode第一刷_Merge Intervals

来源:互联网 发布:网络印刷电商平台 编辑:程序博客网 时间:2024/06/07 18:36

看到这个题我就伤心啊,去微软面试的时候,第一个面试官让我做的题目就是实现集合的交操作,这个集合中的元素就像这里的interval一样,是一段一段的。当时写的那叫一个惨不忍睹,最后果然被拒掉了。。好好练习算法,争取正式招聘的时候拒一次微软,哈哈~

说归说,这道题其实还是比较简单的。先考虑什么样子的集合是可以合并的。设两段集合是[a, b]和[c, d],不失一般性的,假设a<c,那么有下面几种情况:

1. b<c,这说明两段是完全不相交的,没办法合并。

2. b>=c&&b<=d,两段相交了,这个时候新合并出的结合的头应该是a,结尾应该是d。

3. b>d,也就是后一段完全是前一段的子段,那么合并后的集合应该是[a, b]。

注意到,要想从头到尾扫一遍就完成所有的合并,必须实现对所有的段都排一下序,排序的规则是先按起始边界递增,起始边界相同的,按照结束边界递增。实现的时候用传递一个比较函数做参数的库函数就能轻松搞定。排好序之后,从左往右扫,一开始遇到的那一段的起始,一定是新段的起始,然后如果当前的结束位置比遇到的这一段的起始位置大,那说明这两段相交了,结束位置应该延伸到这两段最远的那个端点,然后继续往后找,直到当前段的结束位置比下一段的起始位置还要小,说明两段完全不相交,那么将当前段的结束位置更新为刚刚那个过程中所能延伸到的最远位置,这就完成了一次合并。然后下一次循环时,从合并后的后一段开始。

代码还是比较简洁的,也很好理解:

bool compare(const Interval &a, const Interval &b){    if(a.start != b.start)        return a.start<b.start;    else        return a.end<b.end;}class Solution {public:    vector<Interval> merge(vector<Interval> &intervals) {        int msize = intervals.size();        vector<Interval> res;        if(msize == 0)  return res;        sort(intervals.begin(), intervals.end(), compare);        Interval itv = intervals[0];        int i=0, tpmax=0;        while(i<msize){            tpmax = itv.end;            while(i<msize&&tpmax>=intervals[i].start){                tpmax = max(tpmax, intervals[i].end);                i++;            }            itv.end = tpmax;            if(i==msize){                res.push_back(itv);                break;            }            if(itv.end<intervals[i].start){                res.push_back(itv);                itv = intervals[i];            }        }        return res;    }};


0 0
原创粉丝点击