题目:
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:
可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
思路:
贪心算法:
将所有区间按右端点进行排序,并将第一个区间作为符合条件的初始区间,并记其右端点为right,则按序查找首个 左端点大于等于right的区间,令其为第二个区间。依次类推,直到所有区间遍历完毕。
证明:最优子结构
若存在两个区间,区间i [li,ri] 和区间j [lj,rj]。设区间j是首个(最左侧)区间,左侧没有不重叠的区间,右侧有若干个不重叠的区间。若存在一个区间i,其右侧端点值ri 小于 区间j的右侧端点值rj,则将区间j换位区间i,仍然满足条件。所以我们可以得到,首个区间就是所有可以选择的区间中右端点最小的那个区间。当确定了首个区间之后,所有与首个区间不重合的区间就组成了一个规模更小的子问题。
解答:
方法一:按右边界排序,从左到右进行遍历,让右边界尽可能小
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
if not intervals:
return 0
#将所有区间按右端点进行排序
intervals.sort(key=lambda x: x[1])
n = len(intervals)
right = intervals[0][1]
ans = 1 #ans记录非交叉区间的个数
for i in range(1, n):
if intervals[i][0] >= right:
ans += 1
right = intervals[i][1]
return n - ans
方法二:按左边界排序,从右到左进行遍历,让左边界尽可能大
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
#按左边界进行排序,从右到左遍历,让左边界尽可能大
intervals.sort(key=lambda x:x[0])
#print(intervals)
n=len(intervals)
res=1
maxv=intervals[-1][0]
for i in range(n-2,-1,-1):
if intervals[i][1]<=maxv:
res+=1
maxv=intervals[i][0]
return n-res