NC37 合并区间

题意分析:

将所给的多个区间,将重叠的区间的进行合并。

题解一(贪心):

如有区间如下:

[[10,30],[20,60],[80,100],[150,180]]

合并的结果为:

[[10,60],[80,100],[150,180]]

区间[10,30]和区间[20,60]有重叠的部分,合并后就成为了[10,60]。合并过程如下

  1. 将区间[10,30]的end和区间[20,60] 的start比较,30>20,说明有重叠,更新区间[10,30]的end 为区间[10,30]的end和区间[20,60]的end的较大值。
  2. 如果两个区间没有交集,如区间[10,60]和区间[80,100],前一区间的end小于下一区间的start。直接将没有重合的区间加入到结果中。
    图片说明
    代码实现如下:
static bool cmp(Interval &a, Interval &b) {
    return a.start < b.start;
}

vector<Interval> merge(vector<Interval> &intervals) {
    if(intervals.size()<2) return intervals;
    vector<Interval> ret;
    //按照区间的start从小到大排序
    sort(intervals.begin(), intervals.end(),cmp);
    //把第一个区间加入到结果中
    ret.push_back(intervals[0]);
    for (int i = 1; i < intervals.size(); i++) {
        //从第二个开始,拿该该区间的start与位于结果区间vector的最后一个区间的end比较
        if (intervals[i].start <= ret.back().end) {
            //如果有重叠,更新ret.back的end
            ret.back().end = max(ret.back().end, intervals[i].end);
        } else {
            //没有重叠,直接加入即可
            ret.push_back(intervals[i]);
        }
    }
    return ret;
}

时间复杂度:,时间开销主要在对区间的排序上。

空间复杂度:,没有申请使用额外的空间。

题解二(动态规划):

任何贪心本质上都可以改成动态规划。对于给定的一个区间,我们对他的操作只有两种,第一种直接加入到最后结果中,第二种是与结果中的一个区间进行合并。

假设现在有区间intervals[i],结果区间为,我们设置一个index,表示现在ret中哪个位置需要合并,合并的条件为ret[index-1].end>=interval[i].start, 那么有如下转移方程:

ret[index-1].start = min(ret[index-1].start,intervals[i].start)

ret[index-1].end = min(ret[index-1].end,intervals[i].end)

发生了合并,index不发生改变

如果没有发生合并,那么直接添加该区间,index更新到新的位置

vector<Interval> merge(vector<Interval> &intervals) {

    sort(intervals.begin(), intervals.end(), cmp);
    if (intervals.size() <= 1) {
        return intervals;
    }
    vector<Interval> ret(intervals.size());
    ret[0].start = intervals[0].start;
    ret[0].end = intervals[0].end;
    int index = 1;
    for (int i = 0; i < intervals.size(); i++) {
        if (ret[index - 1].end >= intervals[i].start) {
            ret[index- 1].start= min(ret[index - 1].start, intervals[i].start);
            ret[index - 1].end = max(ret[index - 1].end, intervals[i].end);
        } else {
            index++;
            ret[index- 1].start = intervals[i].start;
            ret[index - 1].end = intervals[i].end;
        }
    }
    return vector<Interval>(ret.begin(),ret.begin()+index);
}

时间复杂度:,我们对所有区间进行了一次排序

空间复杂度:,n为区间长度。