日新刷题 - 435. 无重叠区间

177 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

一 描述

435. 无重叠区间 - 力扣(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 <= 105
  • intervals[i].length == 2
  • -5 * 104 <= starti < endi <= 5 * 104

二 分析

思路1:贪心算法,主要是找到正确的贪心思路

题目的要求是找到需要移除的最小区间数,等价于找到最多的无重叠的区间;

贪心思路:对输入区间集合按照每个区间的end进行升序排序,下一个start比当前区间end大的话,

最大不重叠区间数加一;

然后更新当前区间。

时间复杂度:O(N),只需要一直往前遍历就好了

空间复杂度:不包括Intervals空间应该是O(1)

class Solution:
    def maxnonlapIntervals(self, intervals):
        max_count = 1#无重叠区间至少有一个,一个区间是不会重叠的
        interval_number = len(intervals)
        intervals.sort(key=lambda x:x[1])#原地排序
        target = intervals[0]
        target_end = target[1]
        for interval in intervals:
            if interval[0] >= target_end:
                target = interval
                target_end = target[1]
                max_count += 1
        return max_count
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals: return 0
        return len(intervals) - self.maxnonlapIntervals(intervals)#减去剩余最多的就是需要最少排除的


思路2:动态规划,从每个区间起点开始的动态规划;

class Solution:
    def nonlap(self, interval1, interval2):#判断两个区间是否重叠
        #interval1是在按照起点排序后处于前面的区间
        end1 = interval1[1]
        start2 = interval2[0]
        if start2 >= end1:
            return True
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals: return 0
        dp = [1 for i in range(len(intervals))]#初始化全为1,因为在每个区间,都至少存在一个不重叠的子区间
        intervals.sort(key=lambda x:x[0])
        for i in range(1, len(intervals)):
            for j in range(i-1, -1, -1):#j往回找
                if self.nonlap(intervals[j], intervals[i]):
                    dp[i] = dp[j] + 1#找到第一个不重叠的区间后利用递推关系式赋值
                    break#内循环结束  
        return len(intervals) - dp[len(intervals)-1]#返回需要去掉的区间数