以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]] 输出:[[1,6],[8,10],[15,18]] 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]] 输出:[[1,5]] 解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
提示:
1 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104
很简单的题目,关键看怎么想,直接上代码了,不懂私信或者留言
class Solution {
/**本题的思路是:先把原来的数组按照第一维从小到大排序,如果第一维相同按照第二位从大到小排序(第二维无所谓,从小到大也许)
这样就能保证类似(1,2),(1,6)这样的区间排完序之后是(1,6)(1,2),这样遍历完第一个区间之后获得的end是6,第二个区间被第一个区间包围可以忽略
然后如果下个区间是(7,10)就把第一个进行结算,如果下个是(3,8)就把end扩展到8并试图继续扩展*/
public int[][] merge(int[][] intervals) {
/**如果只有一个区间就没啥好合并的了,直接返回即可 */
if(intervals.length == 1) {
return intervals;
}
/**大于1个区间先排序,排序规则:按照第一维(区间开始)从小到大进行排序,如果第一维相同按照第二位从大到小排序 */
Arrays.sort(intervals, (a,b)->a[0] != b[0]? a[0] - b[0] : b[1] - a[1]);
/**把第一个区间的开头和结尾定义为start和end,每遍历完一个区间再给这两个赋值*/
int start = intervals[0][0];
int end = intervals[0][1];
/**为减少空间浪费,我这里复用intervals作为结果数组,但是大概率是装不满的,所以需要定义一个validLen表示结果的有效长度,目前还没有*/
int validLen = 0;
for(int i = 1; i < intervals.length; i++) {
/**如果这个区间被之前的区间覆盖了,就跳过 */
if(intervals[i][0] >= start && intervals[i][1] <= end) {
continue;
}
/**intervals[i][0]肯定是大于start的,如果intervals[i][1]小于等于end,那前面的if就返回了,所以这里intervals[i][1]肯定比end大,可以扩展end*/
if(intervals[i][0] <= end) {
end = intervals[i][1];
} else {
/**如果不重合就结算前一个区间并开始下个区间 */
intervals[validLen][0] = start;
intervals[validLen ++][1] = end;
/**开始下个区间,重新计算start和end */
start = intervals[i][0];
end = intervals[i][1];
}
}
/**对于最后一个区间,假设它和上个区间重合则它只是扩展了上个区间,还没结算
如果它和上个区间不重合,则开始了一个新的区间,也没有结算
这两种情况都需要把最后一个区间结算一下 */
intervals[validLen][0] = start;
intervals[validLen++][1] = end;
/**拷贝有效的长度返回 */
return Arrays.copyOf(intervals, validLen);
}
}