夯实算法-无重叠区间

124 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天,点击查看活动详情

题目:LeetCode

给定一个区间的集合 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<=1051 <= intervals.length <= 10^5
  • intervals[i].length == 2
  • 5104 <=starti <endi <=5104-5 * 10^4 <= starti < endi <= 5 * 10^4

解题思路

根据题意可知将区间按照起点从大到小进行排序 以当前区间为基础,判断其与下个区间是否有交集

  • 如果有交集,那么就应该删除其中一个区间,所以count++ 应该删除哪个区间呢?
  • 应该删除两个区间中较长的区间,所以我们将两个区间的右边界设置为较小的右边界,形式上的将较长区间缩短了
  • 另外,重要点在于首先按照起点大小排序,这样左边界永远递增,省去了对左边界的判断

通过顺序遍历的方式,即可拿到上一个区间的范围。 如果当前区间在上一个区间内,我们对当前区间的结束下标记录为上一个区间的结束下标,同时进行计数即可。

代码实现

public int eraseOverlapIntervals(int[][] intervals) {
    // 按照区间起点从大到小排序
    Arrays.sort(intervals, new Comparator < int[] > () {
        public int compare(int[] nums1, int[] nums2) {
            return nums1[0] - nums2[0];
        }
    });
    int count = 0;
    for (int i = 0; i < intervals.length - 1; i++) {
        if (intervals[i][1] > intervals[i + 1][0]) {
            count++;
            int val = Math.min(intervals[i][1], intervals[i + 1][1]);
            intervals[i][1] = val;
            intervals[i + 1][1] = val;
        }
    }
    return count;
}

运行结果

Snipaste_2023-03-03_22-22-42.png

复杂度分析

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)  一起分享知识, Keep Learning!