区间调度

📌 核心概念

区间调度问题是贪心算法的经典应用,核心思想是按结束时间排序,选择最早结束的活动。

贪心策略:每次选择结束时间最早且不冲突的区间,这样能为后续活动留出最多时间。

💻 算法实现

🎯 经典应用

💡 解题技巧

1. 排序策略选择

  • 按结束时间排序:最多不重叠区间、射箭问题
  • 按开始时间排序:会议室判断、合并区间
  • 按区间长度排序:某些特殊情况

3. 扫描线技巧

将区间的开始和结束分开处理,模拟扫描线从左到右扫描:

  • 遇到开始点:计数+1
  • 遇到结束点:计数-1
  • 记录过程中的最大值

📊 复杂度分析

问题排序依据时间复杂度空间复杂度
无重叠区间结束时间O(n log n)O(1)
会议室开始时间O(n log n)O(1)
会议室II扫描线O(n log n)O(n)
射箭问题结束位置O(n log n)O(1)
合并区间开始位置O(n log n)O(n)
划分字母区间无需排序O(n)O(1)

Go 代码

// 无重叠区间
func eraseOverlapIntervals(intervals [][]int) int {
    if len(intervals) == 0 {
        return 0
    }
 
    // 按结束时间排序
    sort.Slice(intervals, func(i, j int) bool {
        return intervals[i][1] < intervals[j][1]
    })
 
    count := 1
    end := intervals[0][1]
 
    for i := 1; i < len(intervals); i++ {
        if intervals[i][0] >= end {
            count++
            end = intervals[i][1]
        }
    }
 
    return len(intervals) - count
}
 
// 会议室II
func minMeetingRooms(intervals [][]int) int {
    if len(intervals) == 0 {
        return 0
    }
 
    starts := make([]int, len(intervals))
    ends := make([]int, len(intervals))
 
    for i, interval := range intervals {
        starts[i] = interval[0]
        ends[i] = interval[1]
    }
 
    sort.Ints(starts)
    sort.Ints(ends)
 
    rooms := 0
    maxRooms := 0
    s, e := 0, 0
 
    for s < len(starts) {
        if starts[s] < ends[e] {
            rooms++
            if rooms > maxRooms {
                maxRooms = rooms
            }
            s++
        } else {
            rooms--
            e++
        }
    }
 
    return maxRooms
}
 
// 合并区间
func merge(intervals [][]int) [][]int {
    if len(intervals) == 0 {
        return [][]int{}
    }
 
    sort.Slice(intervals, func(i, j int) bool {
        return intervals[i][0] < intervals[j][0]
    })
 
    merged := [][]int{intervals[0]}
 
    for i := 1; i < len(intervals); i++ {
        last := merged[len(merged)-1]
        if intervals[i][0] <= last[1] {
            if intervals[i][1] > last[1] {
                last[1] = intervals[i][1]
            }
        } else {
            merged = append(merged, intervals[i])
        }
    }
 
    return merged
}

🎯 经典题目

题目LeetCode难度关键点
无重叠区间435中等按结束时间排序
会议室252简单判断冲突
会议室II253中等扫描线
射箭引爆气球452中等同无重叠区间
合并区间56中等按开始时间排序
插入区间57中等合并变形
划分字母区间763中等记录最后位置
汇总区间228简单连续数字

返回:贪心算法