学习记录:js算法(六十九):合并区间

文章目录

合并区间

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

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

示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

思路一

js 复制代码
function merge(intervals) {
    // 第一步:按照区间起始位置排序
    intervals.sort((a, b) => a[0] - b[0]);

    // 初始化结果数组,至少包含第一个区间
    const merged = [intervals[0]];

    // 遍历排序后的区间列表
    for (let i = 1; i < intervals.length; i++) {
        const current = intervals[i];
        const lastMerged = merged[merged.length - 1];

        // 如果当前区间的起始位置在上一区间结束位置之后,说明无重叠,直接添加
        if (current[0] > lastMerged[1]) {
            merged.push(current);
        } else {
            // 否则,有重叠,更新上一区间的结束位置
            lastMerged[1] = Math.max(lastMerged[1], current[1]);
        }
    }

    return merged;
}

讲解

  1. 排序:首先,对输入的区间列表按照每个区间的起始位置进行升序排序。这样可以确保我们在遍历时能从左到右处理区间,更容易发现和处理重叠。
  2. 合并:遍历排序后的区间列表。对于每个区间,如果它的起始位置在结果数组的最后一个区间的结束位置之后,说明它们不重叠,直接将其加入结果数组。否则,说明有重叠,此时更新结果数组中最后一个区间的结束位置,使其覆盖当前区间的结束位置。
  3. 终止条件:遍历完整个区间列表后,结果数组即为合并后不重叠的区间列表。

思路二

js 复制代码
/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function (intervals) {
    if (intervals.length === 0) return [];

    // 找到最大结束时间
    let maxEnd = 0;
    for (const interval of intervals) {
        maxEnd = Math.max(maxEnd, interval[1]);
    }

    // 创建一个布尔数组来标记每个时间点
    const timeline = new Array(maxEnd + 1).fill(false);

    // 标记每个区间
    for (const [start, end] of intervals) {
        for (let i = start; i <= end; i++) {
            timeline[i] = true;
        }
    }

    // 生成合并后的区间
    const merge = [];
    let start = -1;

    for (let i = 0; i < timeline.length; i++) {
        if (timeline[i]) {
            if (start === -1) {
                start = i; // 找到新的开始
            }
        } else {
            if (start !== -1) {
                merge.push([start, i - 1]); // 结束当前区间
                start = -1; // 重置开始
            }
        }
    }

    // 如果最后一个区间没有结束
    if (start !== -1) {
        merge.push([start, maxEnd]);
    }
    return merge;
};

讲解

  1. 找到最大结束时间:首先遍历所有区间,找到最大的结束时间,以便创建一个合适大小的布尔数组 timeline
  2. 标记区间:遍历每个区间,标记从 startend 的所有时间点为 true
  3. 生成合并后的区间:遍历 timeline 数组,找到连续标记为 true 的时间段,并将其作为合并后的区间添加到结果中。
  4. 处理最后一个区间:如果最后一个区间没有结束(即数组的最后一部分仍然是 true),则将其添加到结果中。
相关推荐
Aniugel8 分钟前
JavaScript高级面试题
javascript·设计模式·面试
BB_CC_DD30 分钟前
四. 以Annoy算法建树的方式聚类清洗图像数据集,一次建树,无限次聚类搜索,提升聚类搜索效率。(附完整代码)
深度学习·算法·聚类
小希爸爸34 分钟前
3、中医基础入门和养生
前端·javascript·后端
我的golang之路果然有问题39 分钟前
快速了解redis,个人笔记
数据库·经验分享·redis·笔记·学习·缓存·内存
天天扭码1 小时前
🔥 别再用 class 了!JS 原型链才是 YYDS
前端·javascript·面试
一天睡25小时1 小时前
React与Vue表单的对比差异
前端·javascript
在澳门喝茶的芦竹1 小时前
React高阶组件——React.momo
javascript·react.js
WEI_Gaot1 小时前
ES6 模板字符串
前端·javascript
长欢1 小时前
保持元素宽高比
javascript