一起刷LeetCode——合并区间(排序算法)

70 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

合并区间

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

来源:leetcode.cn/problems/me…

分析

  • 方法:先排序,后合并
  • 首先把集合按照左区间排序
  • 然后实施合并,把合并之前的区间设为old,区间的首尾分别为start和end,当前的区间为current,新的区间为new,有以下几种情况:
    • 当old和current没有交集,即old.end < current.start,那么new.start = old.start,new.old=current.old
    • 当old和current有交集,当old.end >= current.start,那么new.start = old.start,new.end=max(current.end,old.end)=current.end
    • 当old和current有交集,当old.end >= current.end,那么new.start = old.start,new.end=max(current.end,old.end)=old.end

代码

/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
function merge(intervals) {
  if (!intervals.length) return intervals
  intervals.sort((a, b) => a.start !== b.start ? a.start - b.start : a.end - b.end)
  var prev = intervals[0]
  var res = [prev]
  for (var curr of intervals) {
    if (curr.start <= prev.end) {
      prev.end = Math.max(prev.end, curr.end)
    } else {
      res.push(curr)
      prev = curr
    }
  }
  return res
}

顺便回顾下排序算法

排序算法

  • 可分为两类:原地算法和非原地算法
  • 原地算法指的是算法在更改输入内容时不需要额外的空间,但是可以在进行这些操作时使用少量的非固定大小的空间比如指针,常见的冒泡排序、选择排序、插入排序、堆排序都会原地重新排列元素,因此都属于原地算法。关于快速排序,虽然也是直接操作待排序数组,但是因为采取了分治的策略,因此额外多了O(logn)个空间来管理待排序数组。但通常也被认为是原地算法。
  • JavaScript数组的sort方法属于原地算法,并且默认的排列顺序是把元素转为字符串,通过比较字符串各个字符的Unicode码从而排序,sort方法的参数是一个比较函数,函数入参有两个,表示需要比较的两个元素
  • 本题中就是重写了比较算法,首先比较需要比较的两个区间的开始边界,按照左边界由小到大的顺序排列待排序区间,如果左边界一样,按照右边界从小到大排序,当区间排序完成后,按照分析中的三种情况,依次对区间进行合并

总结

  • 排序算法是基础算法之一,因为JavaScript有内置的sort函数,就直接使用了,后面考虑会使用JavaScript来实现基础的排序算法
  • 今天也是有收获的一天