Java实现区间合并算法详解


本文重点:本文通过Java代码实现经典的 区间合并算法,详细解析排序、合并逻辑及关键代码片段,帮助读者掌握处理重叠区间问题的核心思路。


一、问题描述

给定一组区间 intervals,其中每个区间表示为 [start_i, end_i],要求合并所有重叠的区间,并返回一个不重叠的区间数组,且这些区间需要覆盖所有原始区间。

示例

  • 输入intervals = [[1,3], [2,6], [8,10], [15,18]]
  • 输出[[1,6], [8,10], [15,18]]
  • 解释:区间 [1,3][2,6] 重叠,合并为 [1,6]

二、解决思路

合并重叠区间的核心步骤可分为以下两步:

  1. 按起始点排序
    将区间按起始点从小到大排序,确保遍历时只需关注相邻区间是否重叠。

  2. 线性扫描合并
    维护一个合并后的区间列表,依次将每个区间与列表最后一个区间比较:

    • 若当前区间与前一个区间重叠,合并它们(更新结束点)。
    • 若不重叠,直接加入列表。

三、完整代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals == null || intervals.length == 0) {
            return new int[0][];
        }
        
        // 1. 按区间起始点排序
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
        
        List<int[]> merged = new ArrayList<>();
        merged.add(intervals[0]);
        
        // 2. 合并重叠区间
        for (int i = 1; i < intervals.length; i++) {
            int[] last = merged.get(merged.size() - 1);
            int[] current = intervals[i];
            
            if (current[0] <= last[1]) {
                // 合并区间,更新结束点
                last[1] = Math.max(last[1], current[1]);
            } else {
                merged.add(current);
            }
        }
        
        // 3. 转换List到二维数组
        return merged.toArray(new int[merged.size()][]);
    }
}

四、关键代码解析

1. 区间排序逻辑

Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
  • 作用:按区间的起始点(start)升序排序。
  • 示例
    排序前:[[3,5], [1,2], [4,7]] → 排序后:[[1,2], [3,5], [4,7]]
  • 为什么需要排序
    排序后,所有区间按起始点有序排列,只需比较相邻区间即可判断是否重叠,无需回溯。

2. 合并重叠区间

if (current[0] <= last[1]) {
    last[1] = Math.max(last[1], current[1]);
} else {
    merged.add(current);
}
  • 逻辑
    • 当前区间的起始点(current[0])如果小于等于合并列表中最后一个区间的结束点(last[1]),说明两个区间重叠,合并后的结束点取二者的较大值。
    • 否则,直接将当前区间加入列表。

3. 列表转数组

return merged.toArray(new int[merged.size()][]);
  • 作用:将 List<int[]> 转换为 int[][]
  • 参数意义
    传入 new int[merged.size()][] 是为了指定返回数组的类型为 int[][]。实际返回的数组长度由列表大小决定,传入的数组仅作为类型标记。

五、复杂度分析

  • 时间复杂度

    • 排序:O(n log n)Arrays.sort 使用快速排序。
    • 合并:O(n),线性遍历一次。
      总时间复杂度O(n log n)
  • 空间复杂度

    • 存储合并结果:O(n)(最坏情况下无重叠区间)。
    • 排序的栈空间:O(log n)
      总空间复杂度O(n)

六、总结

  1. 排序是核心:排序后,只需线性遍历即可合并相邻重叠区间。
  2. 合并逻辑:比较当前区间与合并列表最后一个区间,动态更新结束点。
  3. Java类型转换:通过 toArray 指定返回数组类型,避免类型安全问题。

扩展思考:如果输入区间已经按起始点排序,如何优化算法?此时时间复杂度可降至 O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的小白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值