学习记录: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),则将其添加到结果中。
相关推荐
董董灿是个攻城狮8 小时前
AI视觉连载8:传统 CV 之边缘检测
算法
炫饭第一名12 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
进击的尘埃13 小时前
Vue3 响应式原理:从 Proxy 到依赖收集,手撸一个迷你 reactivity
javascript
willow14 小时前
JavaScript数据类型整理1
javascript
LeeYaMaster14 小时前
20个例子掌握RxJS——第十一章实现 WebSocket 消息节流
javascript·angular.js
UIUV14 小时前
RAG技术学习笔记(含实操解析)
javascript·langchain·llm
AI软著研究员15 小时前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish15 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱16 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
FansUnion16 小时前
我如何用 Next.js + Supabase + Cloudflare R2 搭建壁纸销售平台——月成本接近 $0
javascript