贪心算法(Greedy Algorithm)是一种通过选择当前状态下最优的决策来逐步达成全局最优解的方法。

它的核心思想是:在每一步的决策中,都选择当前看起来最好的选择(即局部最优解),希望通过局部最优的选择能够得到全局最优解。

有时候人生不也是这样?
人都看不清自己的全部人生,没法做到一个很长远的规划,普遍的策略就是选当前最有利的选择。

贪心算法的思想

贪心选择指原问题的整体最优解可以通过一系列局部最优的选择得到。 应用同一规则,将原问题变为一个相似的但规模更小的子问题,而后的每一步都是当前最佳的选择。 这种选择依赖于已做出的选择,但不依赖于未做出的选择。


找钱案例

下面以一个经典的“找钱”案例,来切入贪心算法。

问题描述:

假设你有若干种不同面额的硬币(例如:1元、2元、5元、10元等),你需要找零给顾客一定金额的钱,目标是使用尽可能少的硬币数量来找零。

例子:
假设要找零 11元,你有以下几种面额的硬币:1元、2元、5元、10元

你应该如何选择硬币数量最少?

贪心策略:

在这个问题中,贪心算法的思想是每次都选择当前面额最大的硬币,直到找零金额为0。
image

具体的步骤如下:

  1. 先选用面额最大的硬币(尽量多选),然后更新剩余金额。
  2. 重复这个过程,直到剩余金额为0。

具体步骤:

  • 初始金额:11元
  • 选择最大面额硬币:选1枚10元的硬币,剩余金额为 11 - 10 = 1元。
  • 选择最大面额硬币:选1枚1元的硬币,剩余金额为 1 - 1 = 0元。

所以,使用的硬币为:1枚10元 + 1枚1元,总共用了 2枚硬币。

贪心算法的步骤:

  1. 从最大面额硬币开始,选择尽量多的该面额硬币;
  2. 更新剩余金额;
  3. 重复此过程,直到剩余金额为0。

代码:

def greedy_coin_change(coins, amount):
    # coins是硬币面额列表,amount是需要找零的金额
    result = []  # 存储选中的硬币
    for coin in sorted(coins, reverse=True):  # 从大到小排序硬币面额
        while amount >= coin:  # 只要金额大于等于当前面额的硬币
            result.append(coin)  # 选择当前硬币
            amount -= coin  # 减去硬币面额
    return result

测试:

对于硬币面额 1, 2, 5, 10 和需要找零的金额 11,运行该算法的结果会是:

coins = [1, 2, 5, 10]
amount = 11
print(greedy_coin_change(coins, amount))  # 输出 [10, 1]

这表示用了 1枚10元 和 1枚1元,共2枚硬币。

注意:

  • 贪心算法在这个问题中能得到最优解,即最少硬币的数量。每次选择面额最大的硬币是一个局部最优解,最终得到的结果也是全局最优解。
  • 但贪心算法并不是对所有找零钱问题都适用。例如,如果硬币面额为 [1, 3, 4],需要找零金额为 6,贪心算法可能会选择 1个4 元和 2个1 元个硬币,总计 3 枚,但实际上 3 + 3 总共只需要 2 枚硬币,这时贪心算法可能不会给出最优解。因此,贪心算法适用时需要保证满足“贪心选择性质”和“最优子结构”。

优缺点比较

优点

  • 贪心算法相对简单,容易理解,代码易于实现。

缺点

  • 不能保证求得的最后解是最佳解;
    但是由于其只关注于当前的最优解,很多情况下难得到全局最优解。
  • 不能用来求最大值或最小值的问题;
  • 只能求满足某些约束条件的可行解的范围。
posted on 2025-01-07 16:28  Mysticbinary  阅读(392)  评论(0)    收藏  举报