面试算法题 | 合并区间(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 这两个端点。

结语

再见!

相关推荐
打不着的大喇叭28 分钟前
uniapp的光标跟随和打字机效果
前端·javascript·uni-app
无我Code34 分钟前
2025----前端个人年中总结
前端·年终总结·创业
程序猿阿伟36 分钟前
《前端路由重构:解锁多语言交互的底层逻辑》
前端·重构
Wilber的技术分享1 小时前
【机器学习实战笔记 14】集成学习:XGBoost算法(一) 原理简介与快速应用
人工智能·笔记·算法·随机森林·机器学习·集成学习·xgboost
Sun_light1 小时前
6个你必须掌握的「React Hooks」实用技巧✨
前端·javascript·react.js
爱学习的茄子1 小时前
深度解析JavaScript中的call方法实现:从原理到手写实现的完整指南
前端·javascript·面试
莫空00001 小时前
Vue组件通信方式详解
前端·面试
呆呆的心1 小时前
揭秘 CSS 伪元素:不用加标签也能玩转出花的界面技巧 ✨
前端·css·html
susnm1 小时前
Dioxus 与数据库协作
前端·rust
Tanecious.1 小时前
LeetCode 876. 链表的中间结点
算法·leetcode·链表