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难度,但是还是比较好想出来的,就是重写compare,然后对所有集合进行排序,排序之后再进行比较久ok了。
[A,B]与[C,D]
在已经排序的前提下,比较B与C的大小,如果B大,那么合并两个集合,取出D与下一个集合进行比较
如果C大,那么直接添加集合进result。
最后再进行一次判断(最后一个集合是否加入了result中)。
但是第一次提交compare定义出现了错误。
/** * 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) { List<Interval> result = new ArrayList<Interval>(); int len = intervals.size(); if( len < 2 ) return intervals; Comparator<Interval> comparator = new Comparator<Interval>(){ public int compare(Interval i1,Interval i2){ if( i1.start>i2.start) return 1; else return -1; } }; Collections.sort(intervals, comparator); int[] start = new int[len]; int[] end = new int[len]; for( int i = 0;i<len;i++){ start[i] = intervals.get(i).start; end[i] = intervals.get(i).end; } int begin,over; int i = 0,j = 1; while( i< len ){ if( i == len-1){ result.add(intervals.get(i)); return result; } Interval ans = new Interval(); ans.start = start[i]; begin = start[j]; over = end[i]; while( over >= begin ){ over = over>end[j]?over:end[j]; j++; if( j == len) break; begin = start[j]; } ans.end = over; result.add(ans); i = j; j = j+1; } return result; } }
然后发现并不是超时,只是对于compare重写的时候出现了问题。
jdk 1.7以前compare只能返回1与-1,但是1.7以后当两个数相同需要返回0,因为compare(a,b)与compare(b,a)要返回相反的数,所以这里出现了问题,然后稍微修改一下,并且做了一些细微的调整,结果还算满意。
/** * 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) { List<Interval> result = new ArrayList<Interval>(); int len = intervals.size(); if( len < 2 ) return intervals; Comparator<Interval> comparator = new Comparator<Interval>(){ public int compare(Interval i1,Interval i2){ if( i1.start>i2.start) return 1; else if( i1.start == i2.start) return 0; else return -1; } }; Collections.sort(intervals, comparator); int begin,over; int i = 0,j = 1,k = 0; while( i< len && j < len){ Interval ans = new Interval(); ans.start = intervals.get(i).start; begin = intervals.get(j).start; over = intervals.get(i).end; while( over >= begin ){ over = over>intervals.get(j).end?over:intervals.get(j).end; j++; if( j == len) break; begin = intervals.get(j).start; } ans.end = over; result.add(ans); i = j; j = j+1; k++; } if( result.get(k-1).end < intervals.get(len-1).start ) result.add(intervals.get(len-1)); return result; } }
然后发现别人的答案中,有一个很难发现的细节,就是如果将start和end分别放入两个数组中,再进行排序,最后的结果与直接将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 List<Interval> merge(List<Interval> intervals) { List<Interval> result = new ArrayList<Interval>(); int len = intervals.size(); if( len < 2 ) return intervals; int[] start = new int[len]; int[] end = new int[len]; for( int i = 0;i<len;i++){ start[i] = intervals.get(i).start; end[i] = intervals.get(i).end; } Arrays.sort(start); Arrays.sort(end); int begin,over; int i = 0,j = 1; while( i< len ){ if( i == len-1){ result.add(new Interval(start[i],end[i])); return result; } Interval ans = new Interval(); ans.start = start[i]; begin = start[j]; over = end[i]; while( over >= begin ){ over = over>end[j]?over:end[j]; j++; if( j == len) break; begin = start[j]; } ans.end = over; result.add(ans); i = j; j = j+1; } return result; } }