问题:
Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].
代码示例:
分析:
merge的意思是:[1,3], [2,6]之间有重叠的区域,因此可以合并为[1, 6]。
因此这里关键是,判断是否发生重叠。
即前一个数组的后一个值,是否大于后一个数组的前一个值。
然而,这个问题的输入,与上面的例子不一样,是混序的。
因此,我们先按照第一个数进行排序,然后进行合并。
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public List<Interval> merge(List<Interval> intervals) {
return mergeInner(sortIntervals(intervals));
}
//排序
private List<Interval> sortIntervals(List<Interval> intervals) {
//start值有可能想等,因此用List来存储对应的index
TreeMap<Integer, List<Integer>> map = new TreeMap<>();
for (int i = 0; i < intervals.size(); ++i) {
int start = intervals.get(i).start;
if (map.keySet().contains(start)) {
map.get(start).add(i);
} else {
List<Integer> list = new ArrayList<>();
list.add(i);
map.put(start, list);
}
}
//按照start值的顺序,从小到大,重新排列Interval
List<Interval> rst = new ArrayList<>();
for (int key : map.keySet()) {
List<Integer> l = map.get(key);
for (int i : l) {
rst.add(intervals.get(i));
}
}
return rst;
}
public List<Interval> mergeInner(List<Interval> intervals) {
if (intervals == null || intervals.size() < 2) {
return intervals;
}
List<Interval> rst = new ArrayList<>();
//依次比较前一个数组end,和后一个数组的start
for (int i = 0; i < intervals.size();) {
int iStart = intervals.get(i).start;
int iEnd = intervals.get(i).end;
int j = i + 1;
boolean write = false;
for (; j < intervals.size(); ++j) {
int jStart = intervals.get(j).start;
int jEnd = intervals.get(j).end;
//前一个的end,小于后一个的start
//放入结果中
if (iEnd < jStart) {
rst.add(new Interval(iStart, iEnd));
write = true;
break;
} else if (iEnd < jEnd) {
//需要进行merge操作,更新iEnd值
iEnd = jEnd;
}
}
//j越界,没来得及写结果,此处补上
if (!write) {
rst.add(new Interval(iStart, iEnd));
}
//更新i
i = j;
}
return rst;
}
}