Python学习算法系列(7):动态规划与贪心算法
1. 引言
动态规划(Dynamic Programming,DP) 和 贪心算法(Greedy Algorithm) 是两种常见的算法设计思想。它们在许多优化问题中有广泛的应用,能够帮助我们高效地求解最优解。
本篇博客将介绍:
- 动态规划的基本思想
- 贪心算法的基本思想
- 动态规划与贪心算法的应用场景
2. 动态规划(Dynamic Programming)
2.1 动态规划的基本思想
动态规划是通过将一个复杂问题分解为子问题,并将每个子问题的解存储下来,避免重复计算,从而提高效率。动态规划主要适用于最优化问题,例如求最短路径、最大子数组和等。
动态规划的核心
- 最优子结构:问题的最优解可以通过子问题的最优解来构建。
- 子问题重叠:子问题的解可以多次复用。
2.2 动态规划实现示例:斐波那契数列
斐波那契数列的递归实现效率较低,而使用动态规划能够显著提高效率。
def fibonacci(n):
# 创建一个存储计算结果的数组
dp = [0] * (n + 1)
# 基础情况
dp[0], dp[1] = 0, 1
# 迭代计算斐波那契数
for i in range(2, n + 1):
dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
# 测试动态规划版的斐波那契数列
n = 10
print(f"Fibonacci({n}) = {fibonacci(n)}") # 输出 Fibonacci(10) = 55
解释
- 我们用一个数组
dp来存储每个子问题的解。通过从dp[2]开始迭代,直到计算出dp[n],从而求出斐波那契数列的第 n 项。 - 时间复杂度:O(n),空间复杂度:O(n)。
2.3 动态规划的典型问题
- 背包问题:给定一组物品,每个物品有重量和价值,如何选择物品使得总重量不超过背包容量,且总价值最大。
- 最长公共子序列:给定两个字符串,求它们的最长公共子序列(LCS)。
- 最短路径问题:如Dijkstra算法。
3. 贪心算法(Greedy Algorithm)
3.1 贪心算法的基本思想
贪心算法的核心思想是每次选择当前最优解,从而期望通过局部最优的选择得到全局最优解。贪心算法适用于满足贪心选择性质的问题,即每次选择都是最优的,且选择的局部最优解能导致全局最优解。
贪心算法的核心
- 贪心选择性质:每一步的局部选择都是最优的。
- 最优子结构:问题的最优解由子问题的最优解构成。
3.2 贪心算法实现示例:活动选择问题
活动选择问题是经典的贪心算法问题:给定一组活动,每个活动有开始和结束时间,选择最大数量的互不冲突的活动。
def activity_selection(start, finish):
n = len(start)
activities = list(range(n))
# 根据结束时间排序
activities.sort(key=lambda i: finish[i])
# 选择活动
selected_activities = []
last_end_time = -1
for i in activities:
if start[i] >= last_end_time:
selected_activities.append(i)
last_end_time = finish[i]
return selected_activities
# 测试活动选择问题
start = [1, 3, 0, 5, 8, 5]
finish = [2, 4, 6, 7, 9, 9]
selected = activity_selection(start, finish)
print(f"选择的活动编号:{selected}") # 输出 [0, 1, 3, 4]
解释
- 活动按结束时间排序,每次选择第一个不与前一个活动冲突的活动。
- 时间复杂度:O(n log n)(排序)。
3.3 贪心算法的典型问题
- 活动选择问题
- 霍夫曼编码
- 贪心背包问题
4. 动态规划与贪心算法的区别
| 特点 | 动态规划 | 贪心算法 |
|---|---|---|
| 适用问题 | 最优化问题,子问题重叠 | 最优化问题,满足贪心选择性质 |
| 方法 | 通过子问题的解构建整体解 | 每一步做出最优选择,不回溯 |
| 时间复杂度 | 通常较高(O(n^2)、O(nk)等) | 通常较低(O(n log n)等) |
| 结果 | 可以得到最优解 | 可能得到最优解,也可能是近似解 |
5. 总结
- 动态规划:适用于具有最优子结构和子问题重叠的问题,通过存储子问题的解来避免重复计算,时间复杂度通常较高。
- 贪心算法:适用于具有贪心选择性质的问题,通常能够以较低的时间复杂度求解问题,但不能保证得到最优解。
- 动态规划与贪心算法的选择:在实际应用中,需要根据问题的具体性质选择合适的算法。
📢 下一篇 Python学习算法系列(8):回溯算法与分治算法,敬请期待!🚀
💡 如果你喜欢这篇文章,欢迎点赞、收藏,并关注本系列!
1823

被折叠的 条评论
为什么被折叠?



