贪心算法就像一位"永远只选眼前最优解"的冒险家,每次决策都选择当下最有利的选项,逐步逼近全局最优解。下面我用一个拖延症学生赶作业的故事,带你彻底理解其精髓!
📖 故事:拖延症小明的作业危机
小明周日晚上才发现有5项作业没做,每项耗时不同:
数学(60分钟)
, 语文(30分钟)
, 英语(15分钟)
, 物理(45分钟)
, 化学(20分钟)
他要在2小时内(120分钟)完成尽可能多的作业。
⚡ 贪心策略:
每次都选当前耗时最短的作业(快速清掉小任务,腾出更多时间)
- 选最短:英语(15min) → 剩余时间105min
- 选次短:化学(20min) → 剩余85min
- 选第三短:语文(30min) → 剩余55min
- 选第四短:物理(45min) → 剩余10min
- 数学需60min(但剩余时间不足)→ 放弃
结果:完成4项作业(总耗时110min),比按顺序做(只能做3项)更优!
⚙️ 贪心算法核心原理
1. 两大黄金定律
特性 | 含义 | 小明例子 |
---|---|---|
贪心选择性质 | 局部最优选择能导向全局最优解 | 每次选最短作业 → 完成总数最多 |
最优子结构 | 大问题的最优解由子问题最优解组成 | 完成4项 = 前4项最优解的组合 |
2. 与动态规划的区别

💡 贪心永不回溯(高效但可能非全局最优),动态规划会回看历史(准确但更慢)
💻 Java代码实战:作业调度贪心算法
typescript
java
Copy
import java.util.*;
public class GreedyHomework {
public static void main(String[] args) {
// 作业列表:<科目, 耗时>
Map<String, Integer> homework = new HashMap<>();
homework.put("数学", 60);
homework.put("语文", 30);
homework.put("英语", 15);
homework.put("物理", 45);
homework.put("化学", 20);
// 贪心核心:按耗时升序排序
List<Map.Entry<String, Integer>> sortedList = new ArrayList<>(homework.entrySet());
sortedList.sort(Map.Entry.comparingByValue()); // 按耗时排序[11](@ref)
// 执行作业
int totalTime = 120;
List<String> completed = new ArrayList<>();
for (Map.Entry<String, Integer> task : sortedList) {
if (totalTime >= task.getValue()) {
completed.add(task.getKey());
totalTime -= task.getValue();
} else {
break; // 时间不足时停止
}
}
System.out.println("完成作业:" + completed);
System.out.println("剩余时间:" + totalTime + "分钟");
}
}
运行结果:
css
Copy
完成作业:[英语, 化学, 语文, 物理]
剩余时间:10分钟
⚠️ 贪心算法的陷阱:何时会失效?
1. 非标准货币找零问题
若硬币面额为:[1, 5, 11]
,要凑出15元:
-
贪心:11+1+1+1+1 → 5枚硬币
-
实际最优:5+5+5 → 3枚硬币(贪心失效!)
2. 适用条件总结
场景 | 是否适用贪心 | 原因 |
---|---|---|
标准找零(1/5/10) | ✅ 是 | 大面额总能组成最优解 |
非标准找零 | ❌ 否 | 局部最优≠全局最优 |
活动安排问题 | ✅ 是 | 早结束的活动优先保证更多安排8 |
背包问题(物品可分割) | ✅ 是 | 优先选价值密度最高的物品 |
🚨 黄金法则 :使用前必须证明问题满足贪心选择性质!
🌐 经典应用场景与Java实现
1. 活动安排问题(最多不相交区间)
ini
java
Copy
// 按结束时间排序 → 每次选最早结束的活动[8,10](@ref)
Arrays.sort(activities, (a, b) -> a.end - b.end);
int count = 1, lastEnd = activities[0].end;
for (int i = 1; i < activities.length; i++) {
if (activities[i].start >= lastEnd) {
count++;
lastEnd = activities[i].end;
}
}
2. 股票买卖(多次交易)
ini
java
Copy
// 只要今天比昨天涨就卖出[5](@ref)
int profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) {
profit += prices[i] - prices[i - 1];
}
}
3. 霍夫曼编码(数据压缩)
优先合并频率最小的字符 → 构建最优前缀树
💎 总结:一图掌握贪心算法

面试口诀:
眼前利益最大化,全局最优需验证。
活动排序找零钱,子结构是通行证!
试着运行文中的作业调度代码,调整时间限制和作业时长,观察贪心策略的变化。记住:贪心算法是面试高频考点,重点在于识别问题是否具备贪心选择性质!