无重叠区间——贪心

64 阅读1分钟

image.png

代码 1 动态规划:

  1. 按照第一个元素的值,升序排序
  2. dp【i】 表示前 i+1 个元素可以分成多少段
func eraseOverlapIntervals(intervals [][]int) int {
    n := len(intervals)
    if n == 0 {
        return 0
    }
    sort.Slice(intervals, func(i, j int) bool { return intervals[i][0] < intervals[j][0] })
    dp := make([]int, n)
    for i := range dp {
        dp[i] = 1
    }
    for i := 1; i < n; i++ {
        for j := 0; j < i; j++ {
            if intervals[j][1] <= intervals[i][0] {
                dp[i] = max(dp[i], dp[j]+1)
            }
        }
//     for j := i-1; j >= 0; j-- {
//         if intervals[j][1] <= intervals[i][0] {
//             dp[i] = max(dp[i], dp[j]+1)
//             break
//         }
//     }(原代码超时了,改成注释这样就可以了)
    }
    return n - max(dp...)
}

func max(a ...int) int {
    res := a[0]
    for _, v := range a[1:] {
        if v > res {
            res = v
        }
    }
    return res
}

代码 2 贪心:

有个题目跟这个很类似,就是一天之中安排会议次数最多的题目。贪心策略是,区间结束早的先安排,因为这样后面才【有可能】安排到更多的会议次数

得到最多的不重复字段数,最后用 n 减去自己得到的那个数即可

func eraseOverlapIntervals(intervals [][]int) int {
    n := len(intervals)
    if n == 0 {
        return 0
    }
    sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] })
    ans, right := 1, intervals[0][1]
    for _, p := range intervals[1:] {
        if p[0] >= right {
            ans++
            right = p[1]
        }
    }
    return n - ans
}