前言
区间合并需要定位一端的顺序,这样合并起来就非常轻松。
一、合并区间
二、题解
package com.xhu.offer.top100;
import java.util.*;
//合并区间
public class Merge {
/*
target:合并两个重合的区间。
如何定义重合区间?
1-完成重合,直接保留外层区间即可。
2-部分重合,保留左区间的左,右区间的右。
对于完全重合区间,如果是右区间完成重合左区间,那么还得不断合并左边的区间,知道不重合为止。
*/
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, Comparator.comparingInt(o -> o[0]));
List<int[]> rs = new ArrayList<>();
rs.add(intervals[0]);
int len = intervals.length;
for (int i = 1; i < len; i++) {
int[] left = rs.get(rs.size() - 1);
int[] right = intervals[i];
//判断重合情况
//1-不重合
if (left[1] < right[0]) {
rs.add(right);
continue;
}
int leftBound = left[0];//先拿到左边界,看是否合并之后有延申。
//重合情况
left[0] = left[0] < right[0] ? left[0] : right[0];
left[1] = left[1] < right[1] ? right[1] : left[1];
//如果左边界越界,则合并左边的相邻区间
if (left[0] < leftBound) {
int j = rs.size() - 2;
while (j >= 0) {
int[] cur = rs.get(j);
//不重合
if (cur[1] < left[0]) continue;
--j;//不管如何,这个节点该被删除。
//部分重合 || 完全重合但未延申
if (cur[1] >= left[0] && cur[0] <= left[0]) {
left[0] = cur[0];
break;
}
//删节点
int cnt = rs.size() - 2 - j;
while (cnt-- > 0) rs.remove(j + 1);
}
}
}
int[][] res = new int[rs.size()][2];
return rs.toArray(res);
}
}
class Merge2 {
//排完序,就利用好有序就很简单了。
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, Comparator.comparingInt(o -> o[0]));
List<int[]> rs = new ArrayList<>(Collections.singleton(intervals[0]));
for (int i = 1; i < intervals.length; i++) {
int[] left = rs.get(rs.size() - 1);
int[] right = intervals[i];
//判断重合情况,left[0]永远是最小的.
//不重合
if (left[1] < right[0]) {
rs.add(right);
continue;
}
//重合的情况,直接合并
if (left[1] < right[1]) left[1] = right[1];
}
return rs.toArray(new int[0][]);
}
}
总结
1)区间合并
2)问题拆解
参考文献
[1] LeetCode 合并区间