一、题目介绍
题目描述
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [startᵢ, endᵢ]。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
示例
- 示例 1输入:
[[1,3],[2,6],[8,10],[15,18]]输出:[[1,6],[8,10],[15,18]]解释:区间[1,3]和[2,6]重叠,合并为[1,6]。 - 示例 2输入:
[[1,4],[4,5]]输出:[[1,5]]解释:区间[1,4]和[4,5]端点相接,视为重叠区间,需要合并。 - 示例 3输入:
[[4,7],[1,4]]输出:[[1,7]]解释:乱序区间排序后再合并,[1,4]覆盖[4,7],合并为整体。
约束条件
1 <= intervals.length <= 10⁴intervals[i].length == 20 <= startᵢ <= endᵢ <= 10⁴
面试考点
区间类经典贪心算法题,大厂前端、后端面试高频题,核心考察排序 + 一次遍历贪心的思维,同类题还有插入区间、区间交集等。
二、解题核心思路
关键难点思考
直接看乱序区间很难判断是否重叠,比如 [[4,7],[1,4]],肉眼很难快速合并。所以解题分两步走:
-
排序预处理 :把所有区间按照左端点升序排列,保证区间起点从小到大;
-
贪心遍历合并:新建结果数组,逐个和结果里最后一个区间对比:
- 如果当前区间左端点 ≤ 结果最后区间右端点:两个区间重叠 / 相接,更新右端点为两者最大值;
- 如果当前区间左端点 > 结果最后区间右端点:无重叠,直接把当前区间加入结果。
逻辑流程图
- 判空:输入为空数组直接返回
[] - 排序:
intervals.sort((a,b) => a[0]-b[0]) - 初始化结果数组,放入排序后的第一个区间
- 从第二个区间开始循环遍历
- 对比区间边界,重叠则合并,不重叠则新增
- 遍历完成返回结果
三、完整 JavaScript 代码
javascript
运行
ini
/**
* @param {number[][]} intervals
* @return {number[][]}
*/
var merge = function(intervals) {
// 边界:空数组直接返回
if (intervals.length === 0) return [];
// 按区间左端点升序排序
intervals.sort((a, b) => a[0] - b[0]);
const res = [intervals[0]];
for (let i = 1; i < intervals.length; i++) {
const last = res[res.length - 1];
const curr = intervals[i];
// 重叠/相接,更新右端点
if (curr[0] <= last[1]) {
last[1] = Math.max(last[1], curr[1]);
} else {
// 不重叠,直接加入结果
res.push(curr);
}
}
return res;
};
代码逐行注释解析
if (intervals.length === 0) return []处理输入为空的边界用例,避免后续排序、取值报错。intervals.sort((a, b) => a[0] - b[0])JS 数组原生 sort 默认按字符串排序,必须传入比较函数,保证区间按起点从小到大排列。const res = [intervals[0]]结果数组先存入排序后的第一个区间,作为对比基准。- 循环从
i=1开始,取出结果最后一个区间last、当前遍历区间curr。 curr[0] <= last[1]判断重叠:当前区间起点 ≤ 上一个区间终点,说明区间相交或者端点相连,需要合并;右端点取两者最大值,兼容[1,5],[2,3]这种完全包含的场景。- 不满足重叠条件时,说明两个区间完全分开,直接 push 进结果数组。
四、测试用例推演演示
用例 1:[[1,3],[2,6],[8,10],[15,18]]
- 排序后不变:
[[1,3],[2,6],[8,10],[15,18]] - res 初始:
[[1,3]] - i=1,curr=2,6,2 ≤ 3 → 合并,res 变为
[[1,6]] - i=2,curr=8,10,8>6 → push,res:
[[1,6],[8,10]] - i=3,curr=15,18,15>10 → push,最终输出
[[1,6],[8,10],[15,18]]
用例 3:乱序输入 [[4,7],[1,4]]
- 排序后:
[[1,4],[4,7]] - res 初始:
[[1,4]] - i=1,curr=4,7,4 ≤ 4 → 合并,右端点更新为 7
- 结果
[[1,7]]
五、复杂度分析
- **时间复杂度:O (n log n)**排序操作是 O (n log n),单次遍历数组 O (n),排序为主要耗时。
- **空间复杂度:O (log n)**排序算法栈开销;结果数组不计入额外空间开销。
六、拓展思考 & 同类题目
- 变形 1:57. 插入区间给定无重叠有序区间,插入新区间后合并,无需完整排序,可二分查找优化。
- 变形 2:435. 无重叠区间贪心反向题,求最少移除多少区间让所有区间互不重叠。
- 变形 3:986. 区间列表的交集两个有序区间数组,求重叠交集区间。
七、总结
合并区间是贪心算法入门必刷题目,核心套路固定:先排序统一区间顺序,再一次遍历贪心合并。面试写代码时注意两个坑:
- JS 的 sort 不写比较函数会出错;
- 合并右端点必须用 Math.max,不能直接赋值 curr 1,防止区间被完全包含时覆盖错误。