首页 简历|笔试面试

56.合并区间

  • 25年9月4日 发布
  • 182.36KB 共5页
56.合并区间56.合并区间56.合并区间56.合并区间56.合并区间

56. 合并区间

鲁迅曾说,尽量每天都让自己充实一点,你可以刷一个小时的短视频,打一个小

时的王者荣耀,但尽量再留一个小时出来读一下书、教程、博客,让自己的大脑

保持活跃,而不是垃圾场。如果真的没有事情做,刷 LeetCode 确实是一个不错

的选择。好,今天继续坚持来一道 LeetCode 题解,第 56 题——合并区间。

题意

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [startᵢ, endᵢ] 。

请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所

有区间 。

难度

中等

示例

示例 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

假如区间 A[]、B[] 能够合并,我们让 A[] 的左端点比 B[] 的左端点更靠近 0,那么必然会

有 A[1] >= B[0] 条件成立,也只有这样,两个区间才能够合并。

而合并后的区间,如果还要与其他区间合并,也一定满足上面的条件。

在这个条件的基础上,这道题就迎刃而解了。

我们只需要先按照左端点从小到大给所有的区间排序,然后再从小到大依次合并区间并且

加入答案即可。

class Solution{

public int[][] merge(int[][] intervals) {

// 如果区间为空,直接返回空数组

if(intervals.length == 0){

return new int[0][0];

}

//按左端点大小排序

Arrays.sort(intervals, new Comparator<int[]>() {

@Override

public int compare(int[] o1, int[] o2) {

return o1[0] - o2[0];

}

});

List<int[]> ans = new ArrayList<>();

// 合并区间

for(int i = 0 ;i < intervals.length;i++){

// 当前区间的左右端点

int lef = intervals[i][0],rig = intervals[i][1];

// 如果当前区间的左端点小于等于上一个区间的右端点,合并区间

while((i + 1 < intervals.length) && intervals[i + 1][0] <= rig){

rig = Math.max(rig,intervals[i + 1][1]);//合并区间

i++;

}

// 加入答案

ans.add(new int[]{lef,rig});

}

// 以数组形式返回答案

return ans.toArray(new int[ans.size()][0]);

}

}

时间复杂度:$ O(n) $。

我们只用了一次排序,然后把相邻的区间依次合并过去,每个区间只会被扫描一次,所以

时间开销并不会很大。

056.合并区间-20250126113627.png

分析 2

也可以用一个 for 循环来搞定。

第一步,仍然是排序区间,按照区间的起始值 start 进行升序排序,这样可以保证区间按

顺序处理,方便合并。

第二步,遍历排序后的区间,用一个变量 currentInterval 表示当前正在合并的区间。

如果当前区间的 start 大于 currentInterval 的 end,说明没有重叠,将 currentInterval 加

入结果,并更新为当前区间。

如果有重叠,则更新 currentInterval 的 end 为两者的最大值。

第三步,遍历结束后,将最后一个 currentInterval 加入结果。

class Solution {

public int[][] merge(int[][] intervals) {

if (intervals.length <= 1) {

return intervals; // 如果区间少于等于 1,直接返回

}

// 按区间的起始值排序

Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));

// 存储合并后的区间

List<int[]> result = new ArrayList<>();

// 初始化当前区间为第一个区间

int[] currentInterval = intervals[0];

// 遍历剩余区间

for (int i = 1; i < intervals.length; i++) {

// 如果当前区间和遍历的区间有重叠

if (currentInterval[1] >= intervals[i][0]) {

// 合并区间,更新当前区间的结束值

currentInterval[1] = Math.max(currentInterval[1], intervals[i][1]);

} else {

// 没有重叠,将当前区间加入结果,并更新当前区间

result.add(currentInterval);

currentInterval = intervals[i];

}

}

// 将最后一个区间加入结果

result.add(currentInterval);

// 转换结果为二维数组返回

return result.toArray(new int[result.size()][]);

}

public static void main(String[] args) {

Solution solution = new Solution();

int[][] intervals = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};

System.out.println(Arrays.deepToString(solution.merge(intervals))); // 输出:

[[1, 6], [8, 10], [15, 18]]

}

}

效率会更高一些。

056.合并区间-20250126114647.png

总结

像类似这种区间合并的问题,上来就先排序,因为排序后,相邻的区间就可以合并了。

再找到合并的条件,也就是左端点小于等于上一个区间的右端点。

其实问题到最后就很 easy 了。

力扣链接:https://leetcode.cn/problems/merge-intervals/

开通会员 本次下载免费

所有资料全部免费下载! 推荐用户付费下载获取返佣积分! 积分可以兑换商品!
一键复制 下载文档 联系客服