leetcode:56. 合并区间

题目

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

示例:

  1. 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
  2. 输出:[[1,6],[8,10],[15,18]]
  3. 解释:区间 [1,3] [2,6] 重叠, 将它们合并为 [1,6].
  1. 输入:intervals = [[1,4],[4,5]]
  2. 输出:[[1,5]]
  3. 解释:区间 [1,4] [4,5] 可被视为重叠区间。

解答 & 代码

区间问题两个技巧:

  1. 排序:此题是区间合并问题,只需按照起点升序排序即可(若起点相同,终点大小的顺序无所谓)
  2. 画图:画出两个区间所有可能的相对位置,分情况讨论

image.png

  1. class Solution {
  2. private:
  3. // 自定义排序函数
  4. static bool cmp(vector<int> a, vector<int> b)
  5. {
  6. return a[0] < b[0] || (a[0] == b[0] && a[1] > b[1]);
  7. }
  8. public:
  9. vector<vector<int>> merge(vector<vector<int>>& intervals) {
  10. // 1. 排序:对于区间合并问题,按起点升序排序即可(若起点相同,终点大小的顺序无所谓)
  11. sort(intervals.begin(), intervals.end(), cmp);
  12. // 2. 合并区间
  13. vector<vector<int>> result;
  14. result.push_back(intervals[0]); // 先将第一个区间压入结果数组
  15. for(int i = 1; i < intervals.size(); ++i)
  16. {
  17. // case 1 & 2:如果当前区间被结果数组最后一个区间覆盖 or
  18. // 当前区间和结果数组最后一个区间相交
  19. // 则,更新结果数组最后一个区间的右边界
  20. if(intervals[i][0] <= result.back()[1])
  21. result.back()[1] = max(result.back()[1], intervals[i][1]);
  22. // case 3:如果当前区间和结果数组最后一个区间无交集
  23. // 则,将当前区间存入结果数组
  24. else
  25. result.push_back(intervals[i]);
  26. }
  27. return result;
  28. }
  29. };

复杂度分析:设原区间个数为 N

  • 时间复杂度 O(NlogN):排序时间复杂度
  • 空间复杂度 O(1):结果数组不计

执行结果:

  1. 执行结果:通过
  2. 执行用时:28 ms, 在所有 C++ 提交中击败了 74.53% 的用户
  3. 内存消耗:18.4 MB, 在所有 C++ 提交中击败了 69.71% 的用户