【LeetCode】322. 零钱兑换

官方链接

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

示例 1:

输入: coins = [1, 2, 5], amount = 11
输出: 3 
解释: 11 = 5 + 5 + 1

示例 2:

输入: coins = [2], amount = 3
输出: -1

说明:
你可以认为每种硬币的数量是无限的。

方案:动态规划:自下而上

我们采用自下而上的方式进行思考。仍定义 F(i) 为组成金额 i 所需最少的硬币数量,假设在计算 F(i) 之前,我们已经计算出 F(0)-F(i-1) 的答案。 则 F(i) 对应的转移方程应为:

其中 c_j 代表的是第 j 枚硬币的面值,即我们枚举最后一枚硬币面额是 c_j ,那么需要从 i-c_j 这个金额的状态 F(i-c_j) 转移过来,再算上枚举的这枚硬币数量 11 的贡献,由于要硬币数量最少,所以 F(i) 为前面能转移过来的状态的最小值加上枚举的硬币数量 11 。

例子1:假设

coins = [1, 2, 5], amount = 11

则,当 i==0 时无法用硬币组成,为 0 。当 i<0 时,忽略 F(i)

我们可以看到问题的答案是通过子问题的最优解得到的。

例子2:假设

coins = [1, 2, 3], amount = 6

在上图中,可以看到:

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:

        dp = [0] + [amount+1]*amount

        for i in range(1, amount+1):
            for c in coins:
                if i >=c:
                    dp[i] = min(dp[i], dp[i-c]+1)

        return dp[-1] if dp[-1] != amount+1 else -1
发布了39 篇原创文章 · 获赞 12 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/wdh315172/article/details/105420403