LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题

一、题目介绍

题目描述

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [startᵢ, endᵢ]。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

示例

  1. 示例 1输入:[[1,3],[2,6],[8,10],[15,18]]输出:[[1,6],[8,10],[15,18]]解释:区间 [1,3][2,6] 重叠,合并为 [1,6]
  2. 示例 2输入:[[1,4],[4,5]]输出:[[1,5]]解释:区间 [1,4][4,5] 端点相接,视为重叠区间,需要合并。
  3. 示例 3输入:[[4,7],[1,4]]输出:[[1,7]]解释:乱序区间排序后再合并,[1,4] 覆盖 [4,7],合并为整体。

约束条件

  • 1 <= intervals.length <= 10⁴
  • intervals[i].length == 2
  • 0 <= startᵢ <= endᵢ <= 10⁴

面试考点

区间类经典贪心算法题,大厂前端、后端面试高频题,核心考察排序 + 一次遍历贪心的思维,同类题还有插入区间、区间交集等。

二、解题核心思路

关键难点思考

直接看乱序区间很难判断是否重叠,比如 [[4,7],[1,4]],肉眼很难快速合并。所以解题分两步走:

  1. 排序预处理 :把所有区间按照左端点升序排列,保证区间起点从小到大;

  2. 贪心遍历合并:新建结果数组,逐个和结果里最后一个区间对比:

    • 如果当前区间左端点 ≤ 结果最后区间右端点:两个区间重叠 / 相接,更新右端点为两者最大值;
    • 如果当前区间左端点 > 结果最后区间右端点:无重叠,直接把当前区间加入结果。

逻辑流程图

  1. 判空:输入为空数组直接返回 []
  2. 排序:intervals.sort((a,b) => a[0]-b[0])
  3. 初始化结果数组,放入排序后的第一个区间
  4. 从第二个区间开始循环遍历
  5. 对比区间边界,重叠则合并,不重叠则新增
  6. 遍历完成返回结果

三、完整 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;
};

代码逐行注释解析

  1. if (intervals.length === 0) return []处理输入为空的边界用例,避免后续排序、取值报错。
  2. intervals.sort((a, b) => a[0] - b[0])JS 数组原生 sort 默认按字符串排序,必须传入比较函数,保证区间按起点从小到大排列。
  3. const res = [intervals[0]]结果数组先存入排序后的第一个区间,作为对比基准。
  4. 循环从 i=1 开始,取出结果最后一个区间 last、当前遍历区间 curr
  5. curr[0] <= last[1] 判断重叠:当前区间起点 ≤ 上一个区间终点,说明区间相交或者端点相连,需要合并;右端点取两者最大值,兼容 [1,5],[2,3] 这种完全包含的场景。
  6. 不满足重叠条件时,说明两个区间完全分开,直接 push 进结果数组。

四、测试用例推演演示

用例 1:[[1,3],[2,6],[8,10],[15,18]]

  1. 排序后不变:[[1,3],[2,6],[8,10],[15,18]]
  2. res 初始:[[1,3]]
  3. i=1,curr=2,6,2 ≤ 3 → 合并,res 变为 [[1,6]]
  4. i=2,curr=8,10,8>6 → push,res:[[1,6],[8,10]]
  5. i=3,curr=15,18,15>10 → push,最终输出 [[1,6],[8,10],[15,18]]

用例 3:乱序输入 [[4,7],[1,4]]

  1. 排序后:[[1,4],[4,7]]
  2. res 初始:[[1,4]]
  3. i=1,curr=4,7,4 ≤ 4 → 合并,右端点更新为 7
  4. 结果 [[1,7]]

五、复杂度分析

  • **时间复杂度:O (n log n)**排序操作是 O (n log n),单次遍历数组 O (n),排序为主要耗时。
  • **空间复杂度:O (log n)**排序算法栈开销;结果数组不计入额外空间开销。

六、拓展思考 & 同类题目

  1. 变形 1:57. 插入区间给定无重叠有序区间,插入新区间后合并,无需完整排序,可二分查找优化。
  2. 变形 2:435. 无重叠区间贪心反向题,求最少移除多少区间让所有区间互不重叠。
  3. 变形 3:986. 区间列表的交集两个有序区间数组,求重叠交集区间。

七、总结

合并区间是贪心算法入门必刷题目,核心套路固定:先排序统一区间顺序,再一次遍历贪心合并。面试写代码时注意两个坑:

  1. JS 的 sort 不写比较函数会出错;
  2. 合并右端点必须用 Math.max,不能直接赋值 curr 1,防止区间被完全包含时覆盖错误。
相关推荐
candyTong4 小时前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
_柳青杨8 小时前
深入理解 JavaScript 事件循环
前端·javascript
Jack209 小时前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
JustHappy10 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom11 小时前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github
小小杨树11 小时前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
大家的林语冰14 小时前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化
假如让我当三天老蒯15 小时前
模块化:ES Module 与 CommonJS 的区别
前端·面试
沉默王二15 小时前
面试官:RAG 不用向量数据库,用 MySQL 硬扛?我:100 万向量不是很轻松?
mysql·面试·ai编程