算法作业第四章
一、问题定位:选点问题的核心应用
本代码针对的是经典的活动选择问题(选点问题的典型应用场景),问题描述如下:给定n个代表活动的时间区间(对应代码中会议的开始时间c[i].a和结束时间c[i].b),需从中选取数量尽可能多的互不重叠区间(即无法同时开展的活动),最终求解最多可选中的区间数量。
代码采用“选点”思路实现该问题的求解:每选定一个区间,等价于在该区间的结束位置选取一个点;后续选中的区间必须从该点之后开始(即满足p < c[i].a,其中p为上一个选中区间的结束点)。通过统计最终选中的区间数量,即可得到最大不重叠区间数。
二、贪心策略的具体实现
该算法的核心贪心策略为:每次从当前所有可选区间中,选择结束时间最早的区间。具体执行流程如下:
- 排序预处理:将所有区间按照结束时间从小到大排序(对应代码中的
sort(c, c + n, cmp),cmp函数依据结束时间b实现升序排列); - 初始化操作:选定排序后第一个区间(即结束时间最早的区间),记录其结束时间
p = c[0].b,并将最大可选数量初始化为ans = 1; - 遍历筛选:遍历剩余所有区间,若当前区间的开始时间
c[i].a大于上一个选中区间的结束时间p(表明两个区间无重叠),则选中该区间,同时更新p为当前区间的结束时间,并将ans加1; - 结果输出:遍历完成后,
ans即为最多可选择的不重叠区间数量。
三、贪心选择性质的证明
贪心选择性质的定义是:全局最优解可通过一系列局部最优选择(贪心选择)逐步构造,即每一步的局部最优决策最终能导向全局最优解。以下证明该算法的贪心策略满足此性质:
符号定义
设所有区间的集合为S,按结束时间升序排列后的区间序列为c₀, c₁, ..., cₙ₋₁(其中c₀为结束时间最早的区间);OPT(S)表示集合S的全局最优解(即最多不重叠区间数量)。
证明步骤
-
基础情况验证:
- 若
S为空集,则OPT(S)=0; - 若
S仅包含一个区间c₀,则OPT(S)=1。
两种情况下,贪心选择均能直接得到最优解。
- 若
-
核心推导过程:
假设OPT(S)是S的一个全局最优解,且OPT(S)中第一个选中的区间为cₖ(k ≥ 0):- 若
k=0:说明OPT(S)本身以贪心选择的c₀作为首个区间,后续只需求解S中所有与c₀不重叠的区间子集S'的最优解,即OPT(S) = 1 + OPT(S'),贪心选择有效; - 若
k>0:由于c₀的结束时间早于cₖ(排序的固有性质),且cₖ与OPT(S)中后续区间均不重叠,因此c₀与cₖ之后的所有区间也必然不重叠。此时将OPT(S)中的cₖ替换为c₀,得到新解OPT'(S)。
由于仅替换了一个区间,OPT'(S)的区间数量与OPT(S)完全相同,因此OPT'(S)也是S的全局最优解,且OPT'(S)以贪心选择的c₀作为首个区间,后续求解S'的最优解即可。这表明选择c₀这一局部最优决策,能够构造出全局最优解。
- 若
-
归纳推广结论:
对于算法每一步的选择,均可通过上述推导证明:选择当前结束时间最早的区间(局部最优),最终能构造出全局最优解。因此该算法满足贪心选择性质。
四、时间复杂度分析
算法的时间复杂度由排序操作和遍历操作两部分构成,具体分析如下:
- 排序操作:代码中使用
sort函数对n个区间排序,C++的sort函数底层平均情况下为快速排序、最坏情况下为归并排序,时间复杂度均为O(n log n),是算法的主导时间复杂度; - 遍历操作:排序后通过
for循环遍历n个区间,每个区间仅执行一次比较和可能的赋值操作,时间复杂度为O(n); - 总时间复杂度:根据渐进时间复杂度规则,忽略低阶项
O(n),算法的总时间复杂度为O(n log n)(平均情况与最坏情况一致)。
五、对贪心算法的核心理解
贪心算法是一种启发式算法(多数场景下可得到最优解),其核心思想是:每一步决策仅聚焦当前局部最优选择,不预先考虑全局最优,期望通过一系列局部最优决策最终达成全局最优解。
贪心算法的核心特性
- 贪心选择性质:全局最优解可通过局部最优选择逐步构造,这是贪心算法能得到最优解的前提——若不满足该性质,贪心算法仅能得到近似解;
- 最优子结构性质:问题的全局最优解包含其子问题的最优解,这是贪心算法与动态规划的共同前提。二者的区别在于:动态规划会记录子问题的所有解并筛选最优,而贪心算法仅依据局部信息选择一个子问题继续求解,无需回溯。
贪心算法的核心特点
- 无回溯性:每一步选择一旦确定便不可更改,后续决策仅依赖当前局部状态,不涉及之前的决策历史,这使得贪心算法的时间复杂度通常远低于动态规划;
- 场景依赖性:贪心算法并非通用解法,其有效性高度依赖问题本身。例如,活动选择问题(结束时间最早策略)、哈夫曼编码(权重最小合并策略)、Dijkstra最短路径算法(距离起点最近策略)等满足贪心选择性质,可得到最优解;而0-1背包问题不满足该性质,贪心算法仅能得到近似解(完全背包问题可适用贪心);
- 策略多样性:同一可通过贪心解决的问题可能存在多种贪心策略,但仅满足贪心选择性质的策略能得到全局最优解。例如活动选择问题中,“结束时间最早”是有效策略,而“开始时间最早”“区间长度最短”等策略均无法得到最优解。
贪心算法与其他算法的区别
- 与动态规划相比:贪心算法无回溯、无状态记录,时间复杂度更低,但仅适用于满足贪心选择性质的问题;动态规划通过记录子问题状态并回溯,适用范围更广,但时间复杂度更高;
- 与暴力算法相比:贪心算法通过局部最优剪枝大幅缩减搜索空间,时间复杂度显著降低;而暴力算法需枚举所有可能情况,时间复杂度通常为指数级。
总结
- 本代码针对活动选择问题(选点问题),采用“选择结束时间最早的区间”这一贪心策略求解;
- 该算法满足贪心选择性质,可通过局部最优决策构造全局最优解,时间复杂度为
O(n log n); - 贪心算法的核心是“以局部最优推导全局最优”,具备无回溯、高效率的特点,但其有效性依赖问题的贪心选择性质和最优子结构性质。

浙公网安备 33010602011771号