元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
算法基础
▶
复杂度分析
时间复杂度
空间复杂度
渐进符号
▶
算法思想
分治法
贪心算法
回溯法
概率算法
枚举算法
递推算法
递归算法
动态规划
分支限界法
模拟算法
▶
算法分析
正确性证明
性能优化
算法比较
▶
搜索算法
▶
基本搜索
顺序搜索
二分搜索
插值搜索
▶
图搜索
深度优先搜索
广度优先搜索
启发式搜索
▶
高级搜索
双向搜索
A*算法
模式匹配
▶
排序算法
▶
比较类排序
冒泡排序
快速排序
归并排序
插入排序
选择排序
▶
非比较类排序
计数排序
基数排序
桶排序
▶
高级排序
堆排序
希尔排序
外部排序
拓扑排序
▶
图论算法
▶
图的表示
邻接矩阵
邻接表
边集数组
▶
最短路径
Dijkstra算法
Floyd算法
Bellman-Ford算法
最短路径概述
▶
生成树
Prim算法
Kruskal算法
并查集
最小生成树
▶
图的连通性
强连通分量
割点与桥
双连通分量
欧拉路径
▶
动态规划
▶
基础概念
最优子结构
重叠子问题
状态转移方程
▶
经典问题
背包问题
最长公共子序列
编辑距离
▶
优化技巧
空间优化
状态压缩
区间动态规划
▶
字符串算法
▶
字符串匹配
KMP算法
Boyer-Moore算法
Sunday算法
▶
字符串处理
字典树
后缀数组
字符串哈希
▶
压缩算法
游程编码
Huffman编码
LZ77算法
发布时间:
2025-03-21 18:07
↑
☰
# 贪心算法 贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前状态下最好或最优的选择,从而希望导致结果是最好或最优的算法。本文将详细介绍贪心算法的概念、设计思想和典型应用。 ## 什么是贪心算法 贪心算法的核心思想是:在对问题求解时,总是做出在当前看来最好的选择。也就是说,不从整体最优上加以考虑,它所做出的选择只是在某种意义上的局部最优选择。 ## 贪心算法的基本要素 1. 贪心选择性质 - 每一步选择都是局部最优的 - 不考虑子问题的解 - 希望通过局部最优达到全局最优 2. 最优子结构性质 - 问题的最优解包含子问题的最优解 - 子问题的最优解可以递推到最终的最优解 ## 贪心算法的设计步骤 1. 将问题分解为若干个子问题 2. 找出适合的贪心策略 3. 求解每个子问题的局部最优解 4. 将局部最优解堆叠成全局最优解 ## 经典应用 ### 1. 活动选择问题 ```python def activity_selection(start, finish): n = len(start) # 第一个活动总是被选中 selected = [0] k = 0 # 选择下一个不冲突的活动 for i in range(1, n): if start[i] >= finish[k]: selected.append(i) k = i return selected # 示例 start = [1, 3, 0, 5, 8, 5] finish = [2, 4, 6, 7, 9, 9] print(activity_selection(start, finish)) # 输出最大的相容活动集合 ``` ### 2. 分数背包问题 ```python def fractional_knapsack(values, weights, capacity): n = len(values) # 计算性价比 ratios = [(values[i]/weights[i], i) for i in range(n)] ratios.sort(reverse=True) total_value = 0 for ratio, i in ratios: if weights[i] <= capacity: # 整个物品都能装下 total_value += values[i] capacity -= weights[i] else: # 只能装一部分 total_value += ratio * capacity break return total_value # 示例 values = [60, 100, 120] weights = [10, 20, 30] capacity = 50 print(fractional_knapsack(values, weights, capacity)) # 输出最大价值 ``` ### 3. 霍夫曼编码 ```python class Node: def __init__(self, freq, symbol, left=None, right=None): self.freq = freq self.symbol = symbol self.left = left self.right = right self.code = '' def huffman_coding(data): # 统计频率 frequency = {} for char in data: if char in frequency: frequency[char] += 1 else: frequency[char] = 1 # 构建霍夫曼树 nodes = [Node(frequency[symbol], symbol) for symbol in frequency] while len(nodes) > 1: nodes = sorted(nodes, key=lambda x: x.freq) left = nodes[0] right = nodes[1] left.code = '0' right.code = '1' newNode = Node(left.freq + right.freq, left.symbol + right.symbol, left, right) nodes.remove(left) nodes.remove(right) nodes.append(newNode) return nodes[0] ``` ## 贪心算法的优缺点 ### 优点 1. 简单直观 - 思路简单 - 实现容易 2. 效率高 - 不需要回溯 - 时间复杂度通常较低 3. 适用范围广 - 许多实际问题可以用贪心解决 - 可以作为其他算法的启发式方法 ### 缺点 1. 不一定得到最优解 - 局部最优不一定导致全局最优 - 可能错过更好的解 2. 需要证明正确性 - 贪心选择性质的证明可能复杂 - 不是所有问题都适合贪心 ## 贪心算法的应用场景 1. 最小生成树 - Prim算法 - Kruskal算法 2. 最短路径 - Dijkstra算法 3. 任务调度 - 工作排序 - 资源分配 ## 如何判断是否使用贪心算法 1. 问题特征 - 具有最优子结构 - 具有贪心选择性质 2. 解决方案 - 能够通过局部最优推导出全局最优 - 每一步的选择都是确定的 3. 验证方法 - 尝试反证法 - 寻找反例 ## 实际应用中的注意事项 1. 正确性验证 - 确保贪心策略的正确性 - 考虑边界情况 2. 效率优化 - 选择合适的数据结构 - 优化贪心选择的实现 3. 可维护性 - 代码结构清晰 - 注释充分 ## 总结 贪心算法是一种重要的算法设计思想: 1. 通过局部最优选择来构建全局最优解 2. 实现简单,效率高 3. 适用于多种实际问题 在实际应用中,需要仔细分析问题是否满足贪心算法的条件,选择合适的贪心策略,并注意验证算法的正确性。虽然贪心算法不一定能得到最优解,但在许多场景下都是一种简单有效的解决方案。