面试算法题 | 合并区间(Javascript版)

一、题目描述

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

示例 1:

css 复制代码
输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

lua 复制代码
输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104

二、题解

本人错误题解

js 复制代码
var merge = function(intervals) {
    let ansSet=new Set();
    let ans=[];
    let left=0;
    let right=0;
    if(intervals.length===0){
        return [];
    }
    if(intervals.length===1){
        return intervals;
    }
    
    for(let i=0;i<intervals.length;i++){
        for(let j=intervals[i][0];j<=intervals[i][1];j++){
            ansSet.add(j);
        }
    }

    const ansArray = Array.from(ansSet);
    ansArray.sort((a, b) => a - b);   
    while(right<ansArray.length&&left<ansArray.length){
        if(ansArray[right]===ansArray[right+1]-1){
            right++;
        }else{
            ans.push([ansArray[left],ansArray[right]])
            left=right+1;
            right++;
        }
    } 
    return ans;

};

错误之处现在于没有考虑到区间里面的数据是连续的

正确题解

js 复制代码
/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function(intervals) {
    if (!intervals || intervals.length === 0) {
        return []; // 处理空数组的情况
    }

    // 1. 按照起始位置升序排序
    intervals.sort((a, b) => a[0] - b[0]);

    const merged = []; // 用于存储合并后的区间
    let currentInterval = intervals[0]; // 初始化当前区间

    for (let i = 1; i < intervals.length; i++) {
        const nextInterval = intervals[i];

        // 2. 判断是否重叠:nextInterval[0] <= currentInterval[1]
        if (nextInterval[0] <= currentInterval[1]) {
            // 3. 如果重叠,合并区间,选择更大的结束位置
            currentInterval[1] = Math.max(currentInterval[1], nextInterval[1]);
        } else {
            // 4. 如果不重叠,将当前合并好的区间推入结果数组,并更新当前区间
            merged.push(currentInterval);
            currentInterval = nextInterval;
        }
    }

    merged.push(currentInterval); // 5. 添加最后一个合并后的区间
    return merged;
};

核心思想

此题的核心思想是使用贪心算法,具体来说,就是通过排序和迭代来逐步地合并重叠的区间。贪心策略在于:每次都尽可能地合并当前区间,直到遇到不重叠的区间为止。

详细题解

  1. 处理边界情况:

    • 当输入数组 intervals 为空或 null 时,函数立即返回空数组 []。 这是一个良好的编程习惯,避免了可能的空指针或空数组访问错误。
  2. 排序:

    • 使用 intervals.sort((a, b) => a[0] - b[0]) 按区间的起始位置升序排序。 这至关重要,因为排好序后,所有可能重叠的区间都会在数组中相邻。 排序是确保贪心策略能正确实施的关键。
  3. 初始化:

    • merged 数组用于存储合并后的不重叠区间。
    • currentInterval 变量指向当前正在构建的合并区间,初始值为排序后的第一个区间 intervals[0]
  4. 迭代和合并:

    • 循环遍历排序后的 intervals 数组(从第二个区间开始)。

    • 对于每个 nextInterval,检查它是否与 currentInterval 重叠:

      • 如果重叠: 如果 nextInterval[0] <= currentInterval[1],则表示 nextIntervalcurrentInterval 重叠。此时,需要更新 currentInterval 的结束位置,即 currentInterval[1] = Math.max(currentInterval[1], nextInterval[1])。这样做可以确保 currentInterval 能够包含所有重叠区间的范围。
      • 如果不重叠: 如果 nextInterval[0] > currentInterval[1],则表示 nextIntervalcurrentInterval 不重叠。 这意味着当前的 currentInterval 已经合并完成,可以将其添加到 merged 数组中,并用 nextInterval 来更新 currentInterval,开始合并一个新的区间。
  5. 添加最后一个区间:

    • 当循环结束时,通常最后一个合并好的区间还存储在 currentInterval 中,需要将其添加到 merged 数组。
  6. 返回结果:

    • 返回 merged 数组,其中包含所有合并后的不重叠区间。

注意事项

  • 排序: 排序是解决方案的关键。 确保使用正确的排序函数 (a, b) => a[0] - b[0],它按照起始位置升序排列。 如果不排序,或者排序方式不正确,则合并逻辑将会出错。
  • 重叠条件: 重叠的条件是 nextInterval[0] <= currentInterval[1]。 必须正确理解此条件,才能判断两个区间是否重叠。
  • 更新结束位置: 重叠时,必须选择 currentIntervalnextInterval 中较大的结束位置,以确保合并后的区间能覆盖所有重叠的部分。
  • 最后一个区间: 千万不要忘记将最后一个合并好的区间添加到 merged 数组。
  • 空数组处理: 代码已经正确地处理了空数组的情况。 确保你的代码也考虑到这种情况。
  • 数组的不可变性: sort() 方法会改变原数组。 如果你需要保持原数组不变,可以在排序之前先创建一个数组的副本。
  • 区间定义: 必须清楚区间的定义是包含起始位置和结束位置,即 [starti, endi] 包含 startiendi 这两个端点。

结语

再见!

相关推荐
white-persist22 分钟前
轻松抓包微信小程序:Proxifier+Burp Suite教程
前端·网络·安全·网络安全·微信小程序·小程序·notepad++
汉克老师36 分钟前
GESP2025年9月认证C++五级真题与解析(单选题9-15)
c++·算法·贪心算法·排序算法·归并排序·gesp5级·gesp五级
lihao lihao1 小时前
c++红黑树
算法
Sarvartha1 小时前
递推与递归笔记
算法
TracyCoder1231 小时前
LeetCode Hot100(1/100)——1. 两数之和 (Two Sum)
算法·leetcode
敲敲了个代码1 小时前
多标签页强提醒不重复打扰:从“弹框轰炸”到“共享待处理队列”的实战
java·前端·javascript·面试·架构
进击的小头1 小时前
常用数字滤波器的特性与适用场景
c语言·算法
不想上班只想要钱2 小时前
动态类名在 <swiper-slide 的复制项中没有起作用的解决方法
前端·vue.js
weixin_395448912 小时前
tidl_import_mul_rmfsd_psd_u8_3x480x544_bise_raw_dynamic.txt
java·服务器·前端
狐572 小时前
2026-01-19-LeetCode刷题笔记-1292-元素和小于等于阈值的正方形的最大边长
笔记·算法·leetcode