贪心算法详解

贪心算法

贪心算法(Greedy Algorithm)是一种常用的算法设计思想,用于解决最优化问题。贪心算法的基本思想是通过每一步的局部最优选择来达到全局最优解。

在贪心算法中,我们从问题的初始状态开始,通过每一步的选择来逐步构建解决方案,直到达到最终目标。在每一步中,贪心算法选择当前最优的解决方案,而不考虑该选择可能对未来步骤的影响。这种局部最优选择的累积最终希望能够达到全局最优解。

贪心算法的关键在于如何定义局部最优解,并证明通过每一步选择局部最优解最终可以达到全局最优解。如果可以确保通过贪心选择得到的解决方案是全局最优的,那么贪心算法通常是一种高效的求解方法,因为其简单性和高效性。

然而,贪心算法并不适用于所有问题,因为在某些情况下,贪心选择可能导致局部最优解无法达到全局最优解。因此,在使用贪心算法解决问题时,需要仔细分析问题的特性,并验证贪心选择是否能够得到正确的解。

总之,贪心算法是一种基于局部最优选择的算法设计思想,适用于一些特定的最优化问题。通过每一步选择当前最优解决方案,贪心算法希望能够达到全局最优解。然而,在使用贪心算法时需要谨慎分析问题,并验证其正确性。

找零问题

目标:找零钱币数量最少

贪心思路:每一步尽可能用大的面额

# 目标:找零钱币数量最少
def fun(t, n):
    """
    :param t: 钱币的面额
    :param n: 需要找零的钱
    :return:
    """
    m = [0 for _ in t]
    for i, money in enumerate(t):
        m[i] = n // t[i]
        n = n % t[i]
    return m, n  # 最后输出的n为剩余找零的余额

# 面额
t = [100, 50, 20, 10, 5, 1]
print(fun(t, 376))
# 输出结果为:([3, 1, 1, 0, 1, 1], 0)

背包问题

分数背包

问题:如何在有限的容量中装入价值最贵的商品,设商品可以任意切分。

贪心思路:每次把单位价值最大的东西先放进背包

goods = [(60, 10), (100, 20), (120, 30)]
goods.sort(key=lambda x: x[0] / x[1], reverse=True)  # 先按照单位价值最高排序 

def fraction_backpack(goods, w):
    m = [0 for _ in range(len(goods))]
    total_v = 0
    for i, (prize, wight) in enumerate(goods):
        if wight <= w:
            m[i] = 1
            w -= wight
            total_v += prize
        else:
            m[i] = w / wight
            w = 0
            total_v += prize * m[i]
            break
    return m, total_v

print(fraction_backpack(goods, 50))
# ([1, 1, 0.6666666666666666], 240.0)

数字拼接问题

问题:给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。

贪心思路:每次两个组合,把能组成更大元素的放在前面。

用冒泡排序

def largestNumber(nums):
    n = len(nums)
    # ()map(function, iterable) 返回一个迭代器
    #
    # > function -- 函数
    # > iterable -- 序列
    nums = list(map(str, nums))
    # 冒泡排序,每次比较后把小的往后丢
    for i in range(n - 1):
        for j in range(n - i - 1):
            if nums[j] + nums[j + 1] < nums[j + 1] + nums[j]:
                nums[j], nums[j + 1] = nums[j + 1], nums[j]

    return str(int("".join(nums)))

nums = [3, 30, 34, 5, 9]

print(largestNumber(nums))

用自带排序函数

from functools import cmp_to_key
def largestNumber(nums):
    def cmp(x, y):
        return 1 if x + y > y + x else -1

    nums = list(map(str, nums))
    nums.sort(key=cmp_to_key(cmp), reverse=True)
    res = str(int("".join(nums)))
    return res

活动选择问题

问题:如何尽可能多安排活动?

贪心思路:每次都选择最早结束的活动

activities = [(1, 4), (3, 5), (0, 6), (5, 7), (5, 9), (6, 10), (8, 11), (8, 12), (12, 16)]

activities.sort(key=lambda x: x[1])


def fuc(activities):
    res = [activities[0]]
    for i in range(1, len(activities)):
        if activities[i][0] >= res[-1][1]:
            res.append(activities[i])
    return res


print(fuc(activities))

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

现实、狠残酷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值