CPH-第六章 贪心
贪心算法在每一步都做出当前看起来最优的局部最优选择,并因此得到全局的最优选择。
6.1 硬币问题(Coin Problem)
给定一组硬币面额和一个目标金额,要求用最少数量的硬币凑出该金额。
-
一个直观的贪心策略是:每次都选不超过剩余金额的最大面额硬币,直到凑满为止。
- 这个策略并非普遍正确。以欧元硬币为例,贪心法恰好能给出最优解;但在一般的面额系统下,贪心可能失败。
-
核心启示:贪心策略的有效性依赖于问题结构,不能仅凭直觉认定其正确。
6.2 调度(Scheduling)
给定 \(n\) 个事件,每个事件有开始时间和结束时间,要求选出尽可能多的互不重叠事件。
- 考虑三种贪心策略,只有第三种被证明是正确的。
| 策略 | 结果 | 反例直觉 |
|---|---|---|
| 选最短的事件 | ✕ | 一个短事件可能“卡”在两个长事件之间,导致只能选 1 个,而最优解可以选 2 个 |
| 选开始最早的事件 | ✕ | 一个开始很早但结束很晚的事件会独占全部时间,排除了后续多个事件的可能 |
| 选结束最早的事件 | ✓ | 结束越早,留给后续事件的选择空间至少不会更小 |
- 正确性论证采用交换论证:如果最优解没有选择结束最早的那个事件,把它替换成结束最早的事件后,后续可选事件的数量不会减少,因此解不会变差。
6.3 任务与截止日期(Tasks and Deadlines)
给定 \(n\) 个任务,每个任务有持续时间和截止时间。完成一个任务获得 \(d - x\) 分,其中 \(d\) 是截止时间,\(x\) 是实际完成时刻。目标是最大化总分。
-
一个出人意料的结论是:最优顺序完全不依赖截止时间,只需按持续时间从短到长排序即可。
-
正确性同样来自交换论证:如果相邻两个任务中,前一个的持续时间长于后一个,交换它们会使总分严格增加。因此,在最优解中,任意相邻任务都必须满足“短任务在前”,从而整个序列按持续时间升序排列即为最优。
6.4 最小化和(Minimizing Sums)
给定 \(n\) 个数 \(a_1, a_2, \ldots, a_n\),要求找一个值 \(x\),使某个和式最小。
-
这一节展示了贪心思想在连续优化场景中的一种形态:最优解并不出现在端点或均值处
-
\(c = 1\),\(x\) 取在中位数
-
\(c = 2\),\(x\) 取平均值
6.5 数据压缩(Data Compression)
前缀码约束
- 任何一个码字都不能是另一个码字的前缀,否则解码时会产生歧义。满足这一约束的编码对应一棵二叉树:字符位于叶子,从根到叶的路径(左 0 右 1)就是码字。
哈夫曼算法
- 哈夫曼算法的贪心选择——每次都合并当前最轻的两个节点——可被证明能产生加权路径长度最小的二叉树,即最优前缀码。
- 算法流程:
- 为每个字符建立一个节点,权重为其出现频率。
- 反复取出权重最小的两个节点,合并为一个新节点,权重为两者之和。
- 重复直到只剩一个根节点。
- 以字符串
AABACDACA为例:A 的频率为 5,B、C、D 各为 1、2、1。合并过程最终得到码字 A→0、C→10、B→110、D→111,压缩后为 15 bit,优于等长编码的 18 bit。
浙公网安备 33010602011771号