MIT6.046算法设计 L1 学习笔记

区间调度算法 Interval Scheduling / 贪心算法

区间调度算法属于贪心算法;贪心算法是动态规划DP算法的一个特例,其需要满足更多的条件(整体的最优解可以通过一系列的局部最优解得到),相对的,贪心的效率比DP高

一、概念

经典的贪心算法问题 Interval Scheduling(区间调度问题)。 给很多形如 [start, end] 的闭区间,算出这些区间中最多有几个互不相交的区间。

本质是求这些时间区间的最大不相交子集。

二、贪心解法

1.从区间集合R中选择一个区间x,其是在R内结束时间最早的区间

2.从R中删除所有与x相交的区间

3.ans_count++,将x从R中剔除,重复1,2;直到R为空

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public int intervalSchedule(int[][] intvs) {
if (intvs.length == 0) return 0;
// 按 end 升序排序
Arrays.sort(intvs, new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return a[1] - b[1];
}
});
// 至少有一个区间不相交
int count = 1;
// 排序后,第一个区间就是 x
int x_end = intvs[0][1];
for (int[] interval : intvs) {
int start = interval[0];
if (start >= x_end) {
// 找到下一个选择的区间了
count++;
x_end = interval[1];
}
}
return count;
}

为什么根据事件的结束时间从小到大排就可以获取最大不相交子区间数?

因为这个问题符合贪心选择性质

我们按时间顺序观察时间轴, 将每个区间画出,按结束时间从小到大对时间切面进行观察

image-20230923174111230

对于1号,显然其前面不存在与其冲突的区间,其符合要求,同时其终点截断了两个区间,所以这两个区间产生了冲突,将他们排除

对于2号,3号同理

详细的推理看不太懂….

假设存在一个最优解,其中包含的区间数量为 n。我们可以证明,按照结束时间从早到晚选择区间的贪心算法可以得到至少 n 个互不相交的区间。

假设最优解中的第一个区间为 x,结束时间最早,那么贪心算法选择的第一个区间也必然是 x。我们可以将最优解中的第一个区间 x 替换为贪心算法选择的第一个区间,这个新的解仍然是一个合法解,并且包含的区间数量不少于最优解。

接下来,我们需要证明贪心算法选择的第二个区间也是最优解中的一个区间。假设最优解中的第二个区间为 y,结束时间最早。如果 y 与 x 相交,那么由于贪心算法选择的区间 x 的结束时间最早,所以 y 的结束时间一定晚于 x,即 y 的结束时间晚于 x 的结束时间。由于贪心算法选择区间的性质,我们可以将最优解中的第二个区间 y 替换为贪心算法选择的第二个区间。这样做不会减少互不相交的区间数量。

以此类推,我们可以将最优解中的每个区间都替换为贪心算法选择的区间,这样得到的新解仍然是一个合法解,并且包含的区间数量不少于最优解。因此,按照结束时间从早到晚选择区间的贪心算法可以得到至少与最优解一样多的互不相交区间。