前端算法(44)

40 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

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

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

题目解析

思路一

首先我们根据每个区间的起点进行排序,在进行遍历数组,并使用双指针维护一个可以合并的最大合并区间[l, r],l,r初始均指向区间左侧端点,当下一个区间的左侧端点<=r,更新最大合并区间,直到遍历到的区间左端点>r 转3,当遇到一个不可以合并的区间时,保存之前维护的最大区间,并初始化双指针

var merge = function (intervals) {
  let res = [];
  const n = intervals.length;
  const intervals = intervals.sort((a, b) => a[0] - b[0]);
  let p = 0;
  while (p < n) {
    let l = intervals[p][0];
    let r = l;
    while (p < n && intervals[p][0] <= r) {
      r = Math.max(r, intervals[p][1]);
      p++;
    }
    res.push([l, r]);
  }
  return res;
};

思路二

我们先判断传入的数组是否为空,然后在以各子区间左端点为准升序排序,创建临时数组存储每一次比较、合并后的区间,初始值为第一个子区间。在创建返回结果的值,进行循环比较后一个子区间的左端点是否小于前一个子区间的右端点,若符合则需合并,不符合则不需合并,若满足条件,合并后的子区间左端点为前一个子区间的左端点,右端点为前一个子区间和后一个子区间右端点的较大值,若不满足条件或不断合并后某次循环不满足条件时,将现有区间push到结果中,并给curr赋值新区间,继续下一次循环,保证最后一个子区间也push到result里,最后在进行返回结果

/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function(intervals) {
    if (intervals.length < 2) return intervals;
    intervals.sort((a, b) => {
        return a[0] - b[0]
    });
    let curr = intervals[0];
    let result = [];
    for (let interval of intervals) {
        if (interval[0] <= curr[1]) {
            curr[1] = Math.max(curr[1], interval[1]);
        } else {
            result.push(curr);
            curr = interval;
        }
    }
    if (curr.length !== 0) {
        result.push(curr);
    }
    return result;
}