https://leetcode.com/problems/merge-intervals/
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]
.
解题思路:
这题应该没有hard的难度。思路如下:
1. 对原intervals的List根据start排序。
2. 遍历intervals,如果当前interval的start<=前一个interval的end,就合并它们,即将start设置为前一个interval的start,end设置为两者较大的。合并的结果作为前一个interval保存。否则,将前一个interval塞进结果list,当前前一个interval作为前一个interval保存。
3. 重复第2步,直至intervals结束。
还有些边界条件需要考虑,比如遍历到intervals的最后一个元素,无论合并与否,都要将结果加入到result里。
先使用了优先队列,也就是最小堆,占用了额外的O(n)空间。
/** * 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 class Compare implements Comparator<Interval> { public int compare(Interval l1, Interval l2){ return l1.start - l2.start; } } public List<Interval> merge(List<Interval> intervals) { List<Interval> result = new ArrayList<Interval>(); if(intervals == null || intervals.size() == 0) { return result; } PriorityQueue<Interval> queue = new PriorityQueue<Interval>(intervals.size(), new Compare()); for(int i = 0; i < intervals.size(); i++){ queue.add(intervals.get(i)); } Interval current = null; Interval previous = null; while(queue.size() > 0){ current = queue.poll(); if(previous == null) { previous = current; if(queue.size() == 0) { result.add(previous); } continue; } if(current.start > previous.end) { result.add(previous); previous = current; } else { current.start = previous.start; current.end = Math.max(current.end, previous.end); previous = current; } if(queue.size() == 0) { result.add(previous); } } return result; } }
后来感觉可以针对intervals排序,不用额外空间了。
/** * 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 class Compare implements Comparator<Interval> { public int compare(Interval l1, Interval l2){ return l1.start - l2.start; } } public List<Interval> merge(List<Interval> intervals) { List<Interval> result = new ArrayList<Interval>(); if(intervals == null || intervals.size() == 0) { return result; } Collections.sort(intervals, new Compare()); Interval current = null; Interval previous = null; for(int i = 0; i < intervals.size(); i++) { current = intervals.get(i); if(previous == null) { previous = current; if(i == intervals.size() - 1) { result.add(previous); } continue; } if(current.start > previous.end) { result.add(previous); previous = current; } else { current.start = previous.start; current.end = Math.max(current.end, previous.end); previous = current; } if(i == intervals.size() - 1) { result.add(previous); } } return result; } }
不管如何,时间复杂度都是O(n*logn),排序所花。
update 2015/05/21:
二刷。以前的思路很混乱啊。写了一个简单点的。
/** * 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 class Compare implements Comparator<Interval> { public int compare(Interval i1, Interval i2) { return i1.start - i2.start; } } public List<Interval> merge(List<Interval> intervals) { List<Interval> result = new ArrayList<Interval>(); if(intervals == null || intervals.size() == 0 || intervals.size() == 1) { return intervals; } Collections.sort(intervals, new Compare()); Interval pre = intervals.get(0); Interval merge = null; for(int i = 1; i < intervals.size(); i++) { Interval cur = intervals.get(i); if(cur.start > pre.end) { result.add(pre); pre = cur; } else { pre.end = Math.max(pre.end, cur.end); } if(i == intervals.size() - 1) { if(pre == cur) { result.add(cur); } else { pre.end = Math.max(pre.end, cur.end); result.add(pre); } } } return result; } }
其实还有更简单的。直接比较结果集result中的最后一个interval——last和当前interva——cur。如果last.end>=cur.start,于是last.end = max(last.end, cur.end),否则就将cur加入result。
这个代码最为简单,思路也最为清晰。
/** * 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 class Compare implements Comparator<Interval> { public int compare(Interval i1, Interval i2) { return i1.start - i2.start; } } public List<Interval> merge(List<Interval> intervals) { List<Interval> result = new ArrayList<Interval>(); if(intervals == null || intervals.size() == 0 || intervals.size() == 1) { return intervals; } Collections.sort(intervals, new Compare()); result.add(intervals.get(0)); for(int i = 1; i < intervals.size(); i++) { Interval cur = intervals.get(i); Interval lastResult = result.get(result.size() - 1); if(lastResult.end >= cur.start) { lastResult.end = Math.max(lastResult.end, cur.end); } else { result.add(cur); } } return result; } }