435.无重叠区间

132 阅读1分钟

题目:
给定一个区间的集合 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
}