贪心算法求解硬币问题

你能构造出连续值的最大数目

在这里插入图片描述

分析:
在这里插入图片描述

class Solution:
    def getMaximumConsecutive(self, coins: List[int]) -> int:
        sum = 0
        coins.sort()
        for coin in coins:
            if coin > sum + 1:
                return sum + 1
            else:
                sum += coin
        return sum + 1

小Q购物

在这里插入图片描述
分析:
与上一题类似思路,假设前i种面额可以构成的总额为Si,现在对前i+1种面额进行分析,如果a[i+1] <= Si,则开始选择第i+1种的面额,且此时可以取到总额Si+a[i+1]。

尽量用最大的面额!

def func(a, m, n):
    cur = count = i = 0
    if a[0] != 1:
        return -1
    else:
        while cur < m:
            while i + 1 < n and a[i + 1] <= cur + 1:
                i += 1
            cur += a[i]
            count += 1
        return count
m, n = map(int, input().split())
a = []
for _ in range(n):
    a.append(int(input()))
a.sort()
num = func(a, m, n)
print(num)

按要求补齐数组

在这里插入图片描述
分析:
对于正整数 x,如果区间[1,x−1] 内的所有数字都已经被覆盖,且 x 在数组中,则区间[1,2x−1] 内的所有数字也都被覆盖。

假设数字 x 缺失,则至少需要在数组中补充一个小于或等于 x 的数,才能覆盖到 x,否则无法覆盖到 x。

如果区间[1,x−1] 内的所有数字都已经被覆盖,则从贪心的角度考虑,补充 x 之后即可覆盖到 x,且满足补充的数字个数最少。在补充 x 之后,区间 [1,2x−1] 内的所有数字都被覆盖,下一个缺失的数字一定不会小于 2x。

如果当前区间是 [1,x],我们应该添加数字 x + 1,这样可以覆盖的区间为 [1,2*x+1]。如果你选择添加小于 x + 1 的数字,达到的效果肯定没这个区间大。而如果你选择添加大于 x + 1 的数字,那么会导致 x + 1 无法被覆盖。这就是贪心的思想。

class Solution:
    def minPatches(self, nums: List[int], n: int) -> int:
        furthest = i = ans = 0
        while furthest < n:
            # 可覆盖到,直接用前缀和更新区间
            if i < len(nums) and nums[i] <= furthest + 1:
                furthest += nums[i] #  [1, furthest] -> [1, furthest + nums[i]]
                i += 1
            else:
                # 不可覆盖到,增加一个数 furthest + 1,并用前缀和更新区间
                # 如果 nums[i] > furthest + 1,说明我们必须添加一个数 x,其中 1 <= x <= furthest + 1,从贪心的角度我们应该选择  furthest + 1,这在前面已经讲过
                furthest = 2 * furthest + 1 # [1, furthest] -> [1, furthest + furthest + 1]
                ans += 1
        return ans

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值