题目:
给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
算法:
方法一:贪心
移除越少,意味着保留越多。如何保留最多的区间?考虑我们如何选择第一个区间,intervals的left和right是确定了的,第一个区间的右端点越小,右侧空间越大,可能放置的空间就越多。每次选择右端点最小,并且左端点大于等于左侧区间右端点的区间。
func eraseOverlapIntervals(intervals [][]int) int {
sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] })
remainCnt := 1
// 先排序再取right
right := intervals[0][1]
for i := 1; i < len(intervals); i++ {
if intervals[i][0] >= right {
remainCnt++
right = intervals[i][1]
}
}
return len(intervals) - remainCnt
}
方法二:动态规划
等价于「选出最多数量的区间,使得它们互不重叠」。
区间编号j<i,f(i)表示以i为结尾区间的最大不重叠区间数。
f(i) = max(f(j) + 1, f(j-1) + 1... f(0) + 1), j, j-1...0都满足右端点小于等于i的左端点.
学习思路,该方法会超时
func eraseOverlapIntervals(intervals [][]int) int {
// dp[i]代表以区间i结尾的,不重叠区间个数
// 就算i之前的区间全部呗剔除,也有一个区间,初始值为1
dp := make([]int, len(intervals))
for i := range dp {
dp[i] = 1
}
sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] })
for i := range intervals {
for j := 0; j < i; j ++ {
if intervals[j][1] <= intervals[i][0] {
dp[i] = max(dp[i], dp[j] + 1)
}
}
}
maxInterval := 0
for i := range dp {
maxInterval = max(dp[i], maxInterval)
}
return len(intervals) - maxInterval
}
func max(a, b int) int {
if a > b {
return a
}
return b
}