五大基础算法——贪心算法

贪心算法 是一种在每一步选择中都采取当前最优决策,希望通过局部最优解达到全局最优解的算法思想。它简单高效,但并非所有问题都适用。以下是贪心算法的核心概念、适用条件、经典问题及实现方法:


一、核心概念

  1. 局部最优解
    • 在每一步选择中,贪心算法只考虑当前状态下的最优解,而不考虑后续步骤的影响。
  2. 无后效性
    • 当前的选择不会影响后续选择的状态。
  3. 全局最优解
    • 通过一系列局部最优解,最终希望得到全局最优解。

二、适用条件

贪心算法适用于满足以下条件的问题:

  1. 贪心选择性质
    • 问题的全局最优解可以通过一系列局部最优解得到。
  2. 最优子结构
    • 问题的最优解包含其子问题的最优解。
  3. 无后效性
    • 当前的选择不会影响后续选择的状态。

三、经典问题与代码

1. 零钱兑换(硬币问题)

问题描述:给定不同面额的硬币和一个总金额,求最少需要多少枚硬币才能凑成总金额。

python 复制代码
def coinChange(coins, amount):
    coins.sort(reverse=True)  # 从大到小排序
    count = 0
    for coin in coins:
        if amount == 0:
            break
        count += amount // coin
        amount %= coin
    return count if amount == 0 else -1

# 示例
coins = [1, 2, 5]
amount = 11
print(coinChange(coins, amount))  # 输出 3 (5+5+1)
2. 活动选择问题

问题描述:给定一组活动,每个活动有开始时间和结束时间,求最多能安排多少个互不冲突的活动。

python 复制代码
def activitySelection(activities):
    activities.sort(key=lambda x: x[1])  # 按结束时间排序
    selected = []
    last_end = -1
    for start, end in activities:
        if start >= last_end:
            selected.append((start, end))
            last_end = end
    return selected

# 示例
activities = [(1, 4), (3, 5), (0, 6), (5, 7), (8, 9)]
print(activitySelection(activities))  # 输出 [(1, 4), (5, 7), (8, 9)]
3. 最小生成树(Kruskal算法)

问题描述:给定一个带权无向图,求其最小生成树。

python 复制代码
def kruskal(graph):
    edges = sorted(graph['edges'], key=lambda x: x[2])  # 按权重排序
    parent = {node: node for node in graph['nodes']}
    result = []
    
    def find(u):
        while parent[u] != u:
            parent[u] = parent[parent[u]]  # 路径压缩
            u = parent[u]
        return u
    
    for u, v, w in edges:
        if find(u) != find(v):
            result.append((u, v, w))
            parent[find(u)] = find(v)
    return result

# 示例
graph = {
    'nodes': ['A', 'B', 'C', 'D'],
    'edges': [('A', 'B', 1), ('B', 'C', 2), ('C', 'D', 3), ('A', 'D', 4)]
}
print(kruskal(graph))  # 输出 [('A', 'B', 1), ('B', 'C', 2), ('C', 'D', 3)]

四、贪心算法的局限性

  1. 不保证全局最优
    • 贪心算法只能保证局部最优,不一定能得到全局最优解。
  2. 适用问题有限
    • 只有满足贪心选择性质和最优子结构的问题才能使用贪心算法。
  3. 需要证明正确性
    • 使用贪心算法时,必须证明其局部最优解能导致全局最优解。

五、适用问题特征

  • 问题可以分解为一系列子问题。
  • 子问题的最优解能组合成全局最优解。
  • 常见问题包括:区间调度、最小生成树、最短路径、零钱兑换等。

贪心算法是一种高效的算法思想,但需要仔细分析问题是否满足其适用条件。在实际应用中,通常需要结合其他算法(如动态规划)来解决更复杂的问题。

相关推荐
樽酒ﻬق4 分钟前
深度解析 Kubernetes 配置管理:如何安全使用 ConfigMap 和 Secret
安全·贪心算法·kubernetes
爱编程的鱼20 分钟前
C# 结构(Struct)
开发语言·人工智能·算法·c#
啊我不会诶28 分钟前
CF每日4题
算法
uhakadotcom44 分钟前
人工智能如何改变医疗行业:简单易懂的基础介绍与实用案例
算法·面试·github
山北雨夜漫步2 小时前
机器学习 Day14 XGboost(极端梯度提升树)算法
人工智能·算法·机器学习
到底怎么取名字不会重复2 小时前
Day10——LeetCode15&560
c++·算法·leetcode·哈希算法·散列表
chuxinweihui3 小时前
数据结构——二叉树,堆
c语言·开发语言·数据结构·学习·算法·链表
freexyn3 小时前
Matlab自学笔记五十一:(推荐)输入参数的数量和可变数量的输入
笔记·算法·matlab
陈大大陈3 小时前
基于 C++ 的用户认证系统开发:从注册登录到Redis 缓存优化
java·linux·开发语言·数据结构·c++·算法·缓存
数据分析螺丝钉3 小时前
LeetCode 252 会议室 III(Meeting Rooms III)题解与模拟面试
算法·leetcode·职场和发展