Merge Intervals

Question

Problem Statement

Given a collection of intervals, merge all overlapping intervals.

Example

Given intervals => merged intervals:

  1. [ [
  2. [1, 3], [1, 6],
  3. [2, 6], => [8, 10],
  4. [8, 10], [15, 18]
  5. [15, 18] ]
  6. ]

Challenge

O(n log n) time and O(1) extra space.

题解1 - 排序后

初次接触这道题可能会先对 interval 排序,随后考虑相邻两个 interval 的 end 和 start 是否交叉,若交叉则合并之。

Java

  1. /**
  2. * Definition of Interval:
  3. * public class Interval {
  4. * int start, end;
  5. * Interval(int start, int end) {
  6. * this.start = start;
  7. * this.end = end;
  8. * }
  9. */
  10. class Solution {
  11. /**
  12. * @param intervals: Sorted interval list.
  13. * @return: A new sorted interval list.
  14. */
  15. public List<Interval> merge(List<Interval> intervals) {
  16. if (intervals == null || intervals.isEmpty()) return intervals;
  17. List<Interval> result = new ArrayList<Interval>();
  18. // sort with Comparator
  19. Collections.sort(intervals, new IntervalComparator());
  20. Interval prev = intervals.get(0);
  21. for (Interval interval : intervals) {
  22. if (prev.end < interval.start) {
  23. result.add(prev);
  24. prev = interval;
  25. } else {
  26. prev.start = Math.min(prev.start, interval.start);
  27. prev.end = Math.max(prev.end, interval.end);
  28. }
  29. }
  30. result.add(prev);
  31. return result;
  32. }
  33. private class IntervalComparator implements Comparator<Interval> {
  34. public int compare(Interval a, Interval b) {
  35. return a.start - b.start;
  36. }
  37. }
  38. }

源码分析

这里因为需要比较 interval 的 start, 所以需要自己实现 Comparator 接口并覆盖 compare 方法。这里取 prev 为前一个 interval。最后不要忘记加上 prev.

复杂度分析

排序 O(n \log n), 遍历 O(n), 所以总的时间复杂度为 O(n \log n). 空间复杂度 O(1).

题解2 - 插入排序

除了首先对 intervals 排序外,还可以使用类似插入排序的方法,插入的方法在题 Insert Interval 中已详述。这里将 result 作为 intervals 传进去即可,新插入的 interval 为 intervals 遍历得到的结果。

Java

  1. /**
  2. * Definition of Interval:
  3. * public class Interval {
  4. * int start, end;
  5. * Interval(int start, int end) {
  6. * this.start = start;
  7. * this.end = end;
  8. * }
  9. */
  10. class Solution {
  11. /**
  12. * @param intervals: Sorted interval list.
  13. * @return: A new sorted interval list.
  14. */
  15. public List<Interval> merge(List<Interval> intervals) {
  16. if (intervals == null || intervals.isEmpty()) return intervals;
  17. List<Interval> result = new ArrayList<Interval>();
  18. for (Interval interval : intervals) {
  19. result = insert(result, interval);
  20. }
  21. return result;
  22. }
  23. private List<Interval> insert(List<Interval> intervals, Interval newInterval) {
  24. List<Interval> result = new ArrayList<Interval>();
  25. int insertPos = 0;
  26. for (Interval interval : intervals) {
  27. if (newInterval.end < interval.start) {
  28. result.add(interval);
  29. } else if (newInterval.start > interval.end) {
  30. result.add(interval);
  31. insertPos++;
  32. } else {
  33. newInterval.start = Math.min(newInterval.start, interval.start);
  34. newInterval.end = Math.max(newInterval.end, interval.end);
  35. }
  36. }
  37. result.add(insertPos, newInterval);
  38. return result;
  39. }
  40. }

源码分析

关键在 insert 的理解,result = insert(result, interval);作为迭代生成新的 result.

复杂度分析

每次添加新的 interval 都是线性时间复杂度,故总的时间复杂度为 O(1 + 2 + … + n) = O(n^2). 空间复杂度为 O(n).

Reference