贪心算法从 0 开始 —— 第 1 章:入门与零钱兑换问题
作者:就是滴九点半
标签:算法 / 贪心 / JavaScript / 入门
✨ 写在前面
如果你正在学习算法,贪心算法(Greedy Algorithm) 是你一定绕不开的一类技巧。它思路简单,代码精炼,在很多经典题中都有着出色的表现。
但它也“狡猾”得很,不是所有问题都适用。贪心不是万能的,但贪心能让你写出又快又简洁的解法。
这篇系列博客将带你从 0 开始学习贪心算法,从简单到复杂,配合实际的题目与 JavaScript 代码实现,一步步理解和掌握它。
✅ 什么是贪心算法?
贪心算法是一种在每一步选择中都采取当前状态下最优解的策略,希望最终结果也是最优的算法。
✅ 特点:
- 局部最优 ➜ 全局最优
- 不回溯、不考虑整体,只在当前阶段做最好的选择
- 不能解决所有问题,但对一些特定问题特别高效!
🧭 系列导航
我们将以以下几个典型问题作为章节划分,按由易到难的顺序进行讲解:
章节 | 题目 | 难度 |
---|---|---|
✅ 第 1 章 | 最小货币找零 | ⭐ 简单 |
第 2 章 | 区间调度(最多不重叠区间) | ⭐⭐ |
第 3 章 | 跳跃游戏 | ⭐⭐⭐ |
第 4 章 | 加油站补给 | ⭐⭐⭐ |
第 5 章 | Huffman 编码 | ⭐⭐⭐⭐ |
第 6 章 | 字符串压缩 | ⭐⭐⭐⭐ |
🚀 第 1 章:入门贪心算法 + 最小货币找零问题
📌 问题描述
假设你有一堆面额为 [25, 10, 5, 1]
的硬币,现在需要找零 某个金额 n,如何使用最少数量的硬币进行找零?
例如:
输入:n = 41
输出:[25, 10, 5, 1]
(总共 4 个硬币)
💡 思路分析:贪心策略
我们想:每次尽量用面额最大的硬币,就能尽快凑出金额,用的数量也就最少。
贪心算法的三个关键要素:
- 选择范围:
[25, 10, 5, 1]
- 贪心选择策略: 当前金额能选的最大面额硬币
- 无后效性: 这一步选择不会影响后面能否达到最优(注:这个问题中其实并不一定是最优解!但我们先用它来练手)
✅ JavaScript 实现
function greedyChange(coins, amount) {
coins.sort((a, b) => b - a); // 从大到小排序
const result = [];
for (let coin of coins) {
while (amount >= coin) {
amount -= coin;
result.push(coin);
}
}
return result;
}
// 测试
console.log(greedyChange([25, 10, 5, 1], 41)); // 输出:[25, 10, 5, 1]
📈 时间复杂度分析:
- 排序时间:
O(n log n)
(一开始排序面额) - 主循环:
O(amount / min_coin)
(大致)
📌 注意:贪心算法并非总是最优解
举个反例:
如果面额是 [10, 6, 1]
,金额是 12
- 贪心会选:[10, 1, 1] → 共 3 个
- 但实际上最优是:[6, 6] → 共 2 个
所以我们要知道:贪心不适合所有问题,但适合一部分问题。
✅ 小结
- 贪心策略是每一步都选最优
- 贪心不能回头,速度快,但不保证最优解
- 硬币找零是个适合入门的简单问题
📚 下一章预告:区间调度问题
给出一堆会议时间(开始和结束时间),如何安排最多场不冲突的会议?
这个问题是贪心策略的经典代表,让我们在下一章一起解决它吧!
如果你觉得本系列对你有帮助,欢迎点赞、评论或收藏,后续会持续更新其他章节!
如果你有任何建议,也欢迎留言交流!
—— END ——