学习记录: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),则将其添加到结果中。
相关推荐
夜思红尘6 小时前
算法--双指针
python·算法·剪枝
散峰而望6 小时前
【算法竞赛】C++函数详解:从定义、调用到高级用法
c语言·开发语言·数据结构·c++·算法·github
CoderCodingNo6 小时前
【GESP】C++五级真题(贪心思想考点) luogu-B4071 [GESP202412 五级] 武器强化
开发语言·c++·算法
我有一些感想……6 小时前
An abstract way to solve Luogu P1001
c++·算法·ai·洛谷·mlp
前端小L6 小时前
双指针专题(三):去重的艺术——「三数之和」
javascript·算法·双指针与滑动窗口
web小白成长日记7 小时前
在Vue样式中使用JavaScript 变量(CSS 变量注入)
前端·javascript·css·vue.js
C_心欲无痕7 小时前
react - useImperativeHandle让子组件“暴露方法”给父组件调用
前端·javascript·react.js
小小星球之旅7 小时前
CompletableFuture学习
java·开发语言·学习
盐焗西兰花7 小时前
鸿蒙学习实战之路-ArkTS循环渲染_ForEach使用指南
学习·华为·harmonyos
巧克力味的桃子7 小时前
单链表 - 有序插入并输出学习笔记
笔记·学习