算法第四章作业
贪心算法:我的理解
贪心算法是一种在每一步选择中都采取当前状态下最优选择的算法策略。它不像动态规划那样考虑所有可能的子问题,也不像回溯法那样进行系统搜索,而是眼光短浅但高效专注——只关心眼前的“最优”,并相信这样的局部最优选择最终能导向全局最优解。贪心算法的核心魅力在于它的简洁与高效。当我们能够证明“局部最优选择能够导致全局最优解”时,贪心算法往往能提供时间复杂度最低的解决方案。但这种美妙特性并非总是成立,这也是贪心算法的阿喀琉斯之踵——它不能解决所有最优化问题,只有当问题具有“贪心选择性质”和“最优子结构”时,贪心策略才有效。
选点问题:
面对这个问题,我们的第一直觉可能是从区间的起点或中点着手。但经过深入思考,一个更精妙的策略浮现出来:按区间右端点排序,并总是选择当前处理区间的右端点作为放置点。为什么是右端点而非左端点?关键在于最大化每个点的覆盖能力。选择右端点意味着这个点能够尽可能地覆盖更多后续区间,因为它是当前区间能够向右延伸的最远位置。
算法步骤:
排序阶段:将所有区间按照右端点从小到大排序。当右端点相同时,按照左端点从大到小排序(这一细微调整优化了处理效率)
初始选择:选择第一个区间(右端点最小的区间)的右端点作为第一个放置点
迭代覆盖:跳过所有包含当前放置点的区间,找到第一个不被覆盖的区间,选择其右端点作为下一个放置点
重复迭代:继续此过程,直到所有区间都被覆盖
贪心选择性质的证明:
设排序后的区间序列为I₁, I₂, ..., Iₙ,其中I₁的右端点r₁最小。
考虑任意最优解S:
情形一:如果S已经包含r₁,则命题直接成立
情形二:如果S不包含r₁,设S在区间I₁中选择的点为p(p ≤ r₁)
现在进行关键构造:用r₁替换S中的p,得到新解S':
对于I₁:由于p ≤ r₁且r₁是I₁的右端点,所以r₁ ∈ I₁
对于其他任意包含p的区间Iⱼ:因为p ≤ r₁且r₁ ≤ rⱼ(排序保证),所以r₁ ∈ Iⱼ
S'的点数与S相同,且仍然覆盖所有区间
因此,总存在包含r₁的最优解。我们的贪心选择——选取第一个区间的右端点——不会将我们排除在最优解之外。
最优子结构的验证:
贪心算法的有效性不仅需要贪心选择性质,还需要最优子结构:子问题的最优解能够组合成原问题的最优解。在我们跳过所有包含第一个放置点的区间后,剩余的子问题与原始问题具有完全相同的形式。如果我们对子问题的解不是最优的,那么加上第一个点构成的整体解也不可能是最优的,这与我们的归纳假设矛盾。这种自我相似的结构确保了贪心策略的全局有效性。
时间复杂度分析:
排序阶段:对n个区间进行排序,最优时间复杂度为O(n log n)。这是算法的主要开销,也是不可避免的,因为我们需要对输入数据进行组织
扫描阶段:线性遍历排序后的区间,每个区间仅被处理一次,时间复杂度为O(n)
总体复杂度:O(n log n) + O(n) = O(n log n)
浙公网安备 33010602011771号