【LeetCode Hot100】合并区间|排序+贪心,Java实现!图解+代码,小白也能秒懂!

💻 [LeetCode Hot100] 合并区间|排序+贪心,Java实现!图解+代码,小白也能秒懂!

✏️本文对应题目链接:合并区间


📌 题目描述

给定一个区间的集合 intervals,其中 intervals[i] = [starti, endi],请合并所有重叠的区间,并返回一个不重叠的区间数组。

示例:

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

🧠 解题思路(图文分解)

❗ 核心难点

如何高效合并所有重叠的区间?


方法一:排序 + 贪心(黄金思路)✨

关键步骤:

  1. 排序:将所有区间按起始点升序排序
  2. 初始化:创建一个结果列表,将第一个区间加入结果
  3. 遍历区间
    • 如果当前区间与结果列表中的最后一个区间重叠,则合并区间
    • 否则,将当前区间加入结果列表
  4. 返回结果:将结果列表转换为数组

图解合并区间

输入区间:

intervals = [[1,3],[2,6],[8,10],[15,18]]

步骤1:排序

排序后:[[1,3],[2,6],[8,10],[15,18]]

步骤2:初始化

result = [[1,3]]

步骤3:遍历区间

i=1: [2,6] 与 [1,3] 重叠 → 合并为 [1,6] → result=[[1,6]]
i=2: [8,10] 与 [1,6] 不重叠 → 加入结果 → result=[[1,6],[8,10]]
i=3: [15,18] 与 [8,10] 不重叠 → 加入结果 → result=[[1,6],[8,10],[15,18]]

最终结果:

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

🚀 代码实现

import java.util.*;

class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals == null || intervals.length == 0) {
            return new int[0][];
        }

        // 按区间起始点升序排序
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));

        List<int[]> result = new ArrayList<>();
        result.add(intervals[0]); // 将第一个区间加入结果

        // 遍历区间
        for (int i = 1; i < intervals.length; i++) {
            int[] lastInterval = result.get(result.size() - 1);
            int[] currentInterval = intervals[i];

            // 如果当前区间与最后一个区间重叠,则合并
            if (currentInterval[0] <= lastInterval[1]) {
                lastInterval[1] = Math.max(lastInterval[1], currentInterval[1]);
            } else {
                // 否则,将当前区间加入结果
                result.add(currentInterval);
            }
        }

        // 将结果列表转换为数组
        return result.toArray(new int[result.size()][]);
    }
}

💡 复杂度分析

  • 时间复杂度:O(n log n) → 排序复杂度为O(n log n),遍历复杂度为O(n)
  • 空间复杂度:O(log n) → 排序所需的栈空间

方法二:扫描线算法(进阶思路)

关键思路:将区间端点排序后扫描,统计重叠区间。

class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals == null || intervals.length == 0) {
            return new int[0][];
        }

        // 将所有端点排序
        int n = intervals.length;
        int[] starts = new int[n];
        int[] ends = new int[n];
        for (int i = 0; i < n; i++) {
            starts[i] = intervals[i][0];
            ends[i] = intervals[i][1];
        }
        Arrays.sort(starts);
        Arrays.sort(ends);

        List<int[]> result = new ArrayList<>();
        int start = starts[0];
        for (int i = 1; i < n; i++) {
            // 如果当前起始点大于前一个结束点,则区间不重叠
            if (starts[i] > ends[i - 1]) {
                result.add(new int[]{start, ends[i - 1]});
                start = starts[i];
            }
        }
        // 加入最后一个区间
        result.add(new int[]{start, ends[n - 1]});

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

🌟 总结要点

排序核心作用:将区间按起始点排序,便于合并
贪心思想:每次合并尽可能多的重叠区间
适用场景:日程安排、任务调度等区间合并问题


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值