LeetCode探索(61):435-无重叠区间

115 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情

题目

给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠

示例 1:

输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。

示例 2:

输入: intervals = [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。

示例 3:

输入: intervals = [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

提示:

  • 1 <= intervals.length <= 10^5
  • intervals[i].length == 2
  • -5 * 10^4 <= starti < endi <= 5 * 10^4

思考

本题难度中等。

本题和之前的题目用最少数量的箭引爆气球类似,也可以借助贪心算法解决。题目需要返回移除的最少区间数量,等同于先求出不互相重叠的区间的数量,再用所有区间的数量减去该值即可。

我们首先对区间数组进行排序,按照右边界从小到大进行排序。之后,遍历数组判断其他区间的左边界是否与该右边界重叠,不重叠则计数值+1,并更新右边界的值,然后继续遍历。

下面是具体代码。

解答

方法一:贪心

/**
 * @param {number[][]} intervals
 * @return {number}
 */
var eraseOverlapIntervals = function(intervals) {
  if (!intervals.length) {
    return 0
  }
  // 对所有区间按照右边界位置进行排序
  intervals.sort((a, b) => a[1] - b[1])
  // 右边界位置最靠左的是 intervals[0]
  let pos = intervals[0][1]
  // 其他区间的左边界要 >= pos,这样不会有重叠
  let ans = 1
  for (let i = 1; i < intervals.length; i++) {
    if (intervals[i][0] >= pos) {
      ans++
      pos = intervals[i][1]
    }
  }
  return intervals.length - ans
}
// 执行用时:228 ms, 在所有 JavaScript 提交中击败了94.90%的用户
// 内存消耗:73.8 MB, 在所有 JavaScript 提交中击败了66.43%的用户
// 通过测试用例:58 / 58

复杂度分析:

  • 时间复杂度:O(nlogn),其中 n 是区间的数量。排序需要 O(nlogn) 的时间,遍历需要 O(n) 的时间。
  • 空间复杂度:O(logn),即为排序需要使用的栈空间。

参考