「前端刷题」56. 合并区间

357 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

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

 

示例 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] 可被视为重叠区间。

 

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104

思路:

  • 将单个索引用两个单元储存
  • 区间的左边界存在索引的左边,右边界存储在索引的右边
  • 因此,若有区间重合,那么重合点的左边会大于 1;
  • 若区间相邻不重合,则在相邻点的右边会 = 0;

未命名绘图.png

代码

/*
 * @lc app=leetcode.cn id=56 lang=javascript
 *
 * [56] 合并区间
 */

// @lc code=start
/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function (intervals) {
  // 差分数组
  let axis = [];
  intervals.forEach((interval) => {
    let left = axis[2 * interval[0]] || 0;
    let right = axis[2 * interval[1] + 1] || 0;
    axis[2 * interval[0]] = left + 1;
    axis[2 * interval[1] + 1] = right - 1;
  });

  let r = [];
  let i = 0,
    len = axis.length,
    value = 0;
  let left = -1;
  while (i < len) {
    value += axis[i] || 0;

    // value > 0;
    // 1、区间开始的标志
    // 2、区间进行中

    // value == 0
    // 1、区间结束的标志
    // 2、不再区间中

    if (value > 0) {
      if (left == -1) {
        left = Math.floor(i / 2);
      }
    } else if (value == 0) {
      if (left !== -1) {
        r.push([left, Math.floor(i / 2)]);
        left = -1;
      }
    }
    i++;
  }
  return r;
};
// @lc code=end

思路2

/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function(intervals) {
    // sort方法里面的比较函数 详情可以看看MDN a[0]-b[0]类似 a-b 升序 这并不奇怪
   intervals.sort((a,b)=>a[0]-b[0])
   // 注意这里对同一个数组进行了读写操作
   // 存在i+1操作 所以intervals.length-1
   for(let i=0;i<intervals.length-1;i++){
       let start = intervals[i][1]
       let end = intervals[i+1][0]
       if(start>=end){
         // 根据规律 说明这个区间可以合并
         const data = [...intervals[i],...intervals[i+1]]
         const item = [Math.min(...data), Math.max(...data)];
          intervals.splice(i, 2, item);
          i--; // 回退操作 看看新调整的区间可以跟后面的合并不
       }
   }
   return intervals
};