一文吃透贪心算法:从入门到实战,轻松掌握高效算法思

张开发
2026/4/17 23:22:31 15 分钟阅读

分享文章

一文吃透贪心算法:从入门到实战,轻松掌握高效算法思
在算法的世界里贪心算法是一种极具实用性的基础算法它凭借简单易懂、效率极高的特点成为编程面试、算法竞赛和日常开发中的高频考点。不同于动态规划的复杂推导、回溯法的暴力枚举贪心算法用最直接的思路解决问题就像它的名字一样每一步都做出当下最优的选择一步步逼近最终答案。今天我们就从核心原理、适用条件、经典例题、误区避坑四个维度彻底吃透贪心算法。一、贪心算法到底是什么1. 核心定义贪心算是一种启发式算法核心思想是在问题的每一个决策阶段都选择当前状态下的最优解局部最优不回溯、不考虑后续影响通过累积局部最优最终得到全局最优解。简单来说就是走一步看一步每一步都选当下最好的绝不反悔。这种“短视”的选择方式省去了复杂的全局预判让算法实现起来格外简洁高效。2. 生活中的贪心小案例不用觉得算法晦涩其实我们每天都在用到贪心思想. 找零钱收银员优先给大面额纸币. 日程安排优先选结束早的活动. 出行规划每次选当前最近站点二、贪心算法的适用条件1. 贪心选择性质局部最优能推导出全局最优2. 最优子结构性质全局最优包含子问题的最优解不满足这两点贪心就会出错。三、解题步骤1. 拆解决策步骤2. 制定贪心策略3. 验证策略是否正确4. 按策略执行5. 复杂度分析四、经典例题例题1活动选择问题问题描述每个活动有开始、结束时间同一时间只能做一个求最多能参加多少活动。贪心策略按结束时间从小到大排序每次选结束最早的。c#include stdio.h #include stdlib.h typedef struct { int start; int end; } Activity; int cmp(const void *a, const void *b) { Activity *x (Activity *)a; Activity *y (Activity *)b; return x-end - y-end; } int maxActivities(Activity act[], int n) { qsort(act, n, sizeof(Activity), cmp); int count 1; int last_end act[0].end; for (int i 1; i n; i) { if (act[i].start last_end) { count; last_end act[i].end; } } return count; } int main() { Activity act[] { {1, 2}, {3, 4}, {0, 6}, {5, 7}, {8, 9}, {5, 9} }; int n sizeof(act) / sizeof(act[0]); printf(最多活动数%d\n, maxActivities(act, n)); return 0; }例题2零钱兑换最少硬币数问题描述给定硬币面额凑出目标金额求最少硬币数量面额满足贪心条件如人民币。#include stdio.h int coinChange(int coins[], int n, int amount) { int count 0; for (int i 0; i n; i) { if (amount 0) break; int use amount / coins[i]; count use; amount - use * coins[i]; } return amount 0 ? count : -1; } int main() { int coins[] {50, 20, 10, 5, 1}; int amount 67; int res coinChange(coins, 5, amount); printf(最少硬币数%d\n, res); return 0; }⚠️ 注意面额不规范时贪心会错例如 [1,3,4] 凑 6贪心得到 4113枚最优是 332枚。例题3跳跃游戏问题描述数组表示该位置能跳的最大长度判断能否跳到最后一位。贪心策略维护当前能到达的最远位置。#include stdio.h int sss(int num[], int n) { int max 0; for (int i 0; i n; i) { if (i max) return 0; if (i num[i] max) { max i num[i]; } if (max n - 1) return 1; } return 1; } int main() { int num1[] {2, 3, 1, 1, 4}; int num2[] {3, 2, 1, 0, 4}; printf(num1%s\n, sss(num1, 5) ? 能到达 : 不能到达); printf(num2%s\n, sss(num2, 5) ? 能到达 : 不能到达); return 0; }五、常见误区1. 不验证条件就用贪心2. 贪心策略选错3. 忽略边界0、空数组、无法凑整等六、经典应用- Kruskal / Prim 最小生成树- Dijkstra 单源最短路- 区间调度、分糖果、分发饼干七、贪心 vs 动态规划- 贪心局部最优不回头效率高- DP记录子问题全局最优更通用八、总结贪心的关键是找对策略 验证正确性。只要满足贪心性质它就是最简单高效的最优解算法。

更多文章