Python 中贪心算法在实际问题中的应用
贪心算法在实际问题中的应用非常广泛,下面介绍三个常见的例子:
-
最小生成树问题:给定一个带权无向图,求一棵生成树使得所有边的权值之和最小。可以使用 Prim 算法或 Kruskal 算法进行求解。每次选择当前未加入生成树的权值最小的边加入生成树中,直到所有节点都被加入。
-
跳跃游戏问题:给定一个非负整数数组,起始位置为数组第一个位置,每个元素表示在该位置最多可以跳跃多少步。判断是否能够到达最后一个位置。可以使用贪心算法进行求解,每次选择能够跳跃最远的位置进行跳跃,直到跳到最后一个位置或无法跳到更远的位置为止。
-
活动安排问题:给定 n 个活动,每个活动有一个开始时间和结束时间,选择一些活动使得它们互不冲突且能够参加的活动数最多。可以使用贪心算法进行求解,每次选择结束时间最早的活动参加,直到没有其他活动与之冲突为止。
下面分别给出代码演示。
- 最小生成树问题(使用 Kruskal 算法)
class UnionFind: def __init__(self, n): self.parent = list(range(n)) def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): self.parent[self.find(x)] = self.find(y) def kruskal(n, edges): uf = UnionFind(n) edges = sorted(edges, key=lambda x: x[2]) res = 0 for u, v, w in edges: if uf.find(u) != uf.find(v): uf.union(u, v) res += w return res n, m = 6, 10 edges = [(0, 1, 3), (0, 2, 2), (1, 2, 4), (1, 3, 5), (1, 4, 4), (2, 4, 6), (2, 5, 7), (3, 4, 2), (4, 5, 5), (3, 5, 6)] print(kruskal(n, edges)) # 输出 18
- 跳跃游戏问题
def can_jump(nums): max_idx = 0 for i in range(len(nums)): if i > max_idx: # 无法到达当前位置 return False max_idx = max(max_idx, i + nums[i]) # 更新最远能到达的位置 return True nums = [2, 3, 1, 1, 4] print(can_jump(nums)) # 输出 True nums = [3, 2, 1, 0, 4] print(can_jump(nums)) # 输出 False
- 活动安排问题
def arrange_activities(activities): activities = sorted(activities, key=lambda x: x[1]) res = [activities[0]] for i in range(1, len(activities)): if activities[i][0] >= res[-1][1]: res.append(activities[i]) return res activities = [(1, 3), (2, 4), (3, 5), (4, 6), (5, 7), (6, 8)] print(arrange_activities(activities)) # 输出 [(1, 3), (4, 6), (6, 8)]
以上是贪心算法在三个实际问题中的应用和代码演示。
相关文章