【LeetCode-贪心】合并区间

题目描述

给出一个区间的集合,请合并所有重叠的区间。
示例:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

题目链接: https://leetcode-cn.com/problems/merge-intervals/

思路

两个区间[a,b]和[c,d]重合的条件是b>=c。首先将所有区间按照区间的左端点升序排序,然后遍历区间,判断当前区间的右端点和下一个区间的左端点之间的大小关系,根据大小关系决定是否合并。代码如下:

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if(intervals.empty()) return {};

        vector<vector<int>> ans;
        sort(intervals.begin(), intervals.end());
        int i = 0;
        int j = 1;
        while(i<intervals.size()){
            j = i;
            int rightMax = intervals[i][1]; // 当前已合并区间的右端点
            while(j<intervals.size() && (intervals[i][1]>=intervals[j][0] || rightMax>=intervals[j][0])){   // 注意这个判断条件
                rightMax = max(rightMax, intervals[j][1]);
                j++;

            }
            ans.push_back({intervals[i][0], rightMax});
            i = j;
        }
        return ans;
    }
};

在判断条件中加了rightMax>=intervals[j][0]是为了防止[[0,2],[1,4],[3,5]]这种情况下出错。

  • 时间复杂度:O(nlogn+n)=O(nlogn)
    O(nlogn)为排序时间,O(n)为区间合并时间,其中n为区间数量。
  • 空间复杂度: O(logn)
    O(logn)为排序所需空间复杂度。

更简洁的写法

思路是一样的,但上面的代码写复杂了,而且判断的条件容易出错,这个写法来自于官方题解。使用ans来存储合并后的区间,对区间进行排序后首先将第一个区间加入到ans中,然后比较ans的最后一个区间的右端点b和下一个区间的左端点c:如果b>=c,则更新b;否则将下一个区间加入到ans中。代码如下:

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if(intervals.empty()) return {};

        vector<vector<int>> ans;
        sort(intervals.begin(), intervals.end());   // 别忘了先排序
        ans.push_back({intervals[0][0], intervals[0][1]});
        for(int i=1; i<intervals.size(); i++){
            int curLen = ans.size()-1;
            if(ans[curLen][1]<intervals[i][0]){
                ans.push_back({intervals[i][0], intervals[i][1]});
            }else{
                ans[curLen][1] = max(intervals[i][1], ans[curLen][1]);
            }
        }
        return ans;
    }
};
  • 时间复杂度:O(nlogn+n)=O(nlogn)
    O(nlogn)为排序时间,O(n)为区间合并时间,其中n为区间数量。
  • 空间复杂度: O(logn)
    O(logn)为排序所需空间复杂度。

还有一种写法

感觉更好理解:

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if (intervals.size() < 2) return intervals;

        sort(intervals.begin(), intervals.end()); // 先排序
        vector<vector<int>> ans;
        int left = intervals[0][0]; // 当前区间[left, right]
        int right = intervals[0][1];
        for (int i = 1; i < intervals.size(); i++) {
            if (right < intervals[i][0]) { // 当前区间和下一个区间不相交
                ans.push_back({left, right});
                left = intervals[i][0];
                right = intervals[i][1];
            } else if (right >= intervals[i][0]) { // 当前区间和下一个区间相交
                if (right <= intervals[i][1]) {
                    right = intervals[i][1]; // 当前区间不包含下一个区间才更新right
                }
            }
        }
        ans.push_back({left, right});
        return ans;
    }
};
posted @ 2020-04-16 16:53  Flix  阅读(150)  评论(0编辑  收藏  举报