合并区间

133 阅读1分钟

这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战

leetcode 合并区间

以数组 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] 可被视为重叠区间。

解题:intervals 数组内有若干的区间,每个区间用两个元素的数组 [starti, endi] 表示,并且starti<=endi,然后每个不同的区间可能会有重叠的区域,那就需要将这两个有重叠区域的区间合并,注意重叠也包括相连的区间, 如[1,4]和[4,6],有重叠部分(第二个区间的开始位置4和第一个区间最后位置4相连),所以合并为[1,6]。所有有重叠的区间都需要合并,最后需要返回一个没有重叠区间的区间集合。 可以发现判断是否重叠是用一个区间的开始位置和另外一个区间的结束位置比较,如果这个开始位置是大于这个结束位置的,那这两个区间并不是重叠的。但是开始位置、结束位置应该是哪个区间的呢? 因为开始位置是肯定小于等于结束位置的,所以对于开始位置较大的区间我们取其开始位置、对于开始位置较小的区间我们取其结束位置来比较。然后因为intervals 数组内的区间是随机分布的,所以为了方便快速的比较, 我们先将intervals 数组按照每一个区间的开始位置从小到大进行排序,那么对于排序后的intervals 数组如果存在需要合并的区间,那么它们一定是相邻的了。然后先准备一个merged空集合,用来存放我们合并的不重叠的区间, 我们再循环遍历intervals数组的区间,然后判断merged集合如果没有元素说明是第一次就将当前遍历的元素区间加入到merged集合,或者当前元素区间的开始位置 > merged集合取出的最后一个元素区间的结束位置, 那就说明这两个区间是没有重叠的,就将当前元素区间加入到merged集合中,否则就是有重叠了,合并区间的操作就是开始位置保留两个区间最小值,结束位置保留两个区间最大值,所以就将merged集合最后一个元素区间的 结束位置修改为两个区间结束位置的最大值就可以了,最后遍历结束返回merged集合(转为二维数组)。

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
        List<int[]> merged = new ArrayList<int[]>();
        for (int[] interval : intervals) {
            int left = interval[0];
            int right = interval[1];
            int size = merged.size();
            if (size == 0 || merged.get(size - 1)[1] < left) {
                merged.add(new int[]{left, right});
            } else {
                merged.get(size - 1)[1] = Math.max(merged.get(size - 1)[1], right);
            }
        }
        return merged.toArray(new int[merged.size()][]);
    }
}