💻 [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]。
🧠 解题思路(图文分解)
❗ 核心难点
如何高效合并所有重叠的区间?
方法一:排序 + 贪心(黄金思路)✨
关键步骤:
- 排序:将所有区间按起始点升序排序
- 初始化:创建一个结果列表,将第一个区间加入结果
- 遍历区间:
- 如果当前区间与结果列表中的最后一个区间重叠,则合并区间
- 否则,将当前区间加入结果列表
- 返回结果:将结果列表转换为数组
图解合并区间
输入区间:
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()][]);
}
}
🌟 总结要点
✅ 排序核心作用:将区间按起始点排序,便于合并
✅ 贪心思想:每次合并尽可能多的重叠区间
✅ 适用场景:日程安排、任务调度等区间合并问题