322. 零钱兑换-动态规划

问题描述

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

示例 1:

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change、

解答

'''

动态规划。
1.原问题为组成amount,而组成amount的所有可等于组成amount-coins[i]加上1,这样就得出了子问题:组成amount-coins[i]
2.dp[i]表示组成i的数字个数
3.边界值:dp[i] = coins[i]
4.状态转移方程:
    dp[i] = min(dp[i-coins[0]],dp[i-coins[1]],....,dp[i-coins[n]])+1

'''

class Solution(object):
    def coinChange(self, coins, amount):
        if amount == 0:
            return 0
        else:
            if len(coins) == 0:
                return -1
            else:
                if len(coins) == 1:
                    if amount % coins[0] == 0:
                        return (amount - (amount % coins[0]))/coins[0]
                    else:
                        return -1
            dp = [0 for _ in range(amount+1)]
            for i in coins:
                if i <= amount:
                    dp[i] = 1
            for i in range(min(coins)+1,amount+1):
                minOfavail = 0
                for j in coins:
                    if j <= amount and i - j > 0 and dp[i-j] > 0:
                        if minOfavail == 0:
                            minOfavail = dp[i-j]
                        else:
                            if minOfavail > dp[i-j]:
                                minOfavail = dp[i-j]
                if dp[i] == 0 and minOfavail != 0:
                    dp[i] = minOfavail + 1
            if dp[amount] == 0:
                dp[amount] = -1
            return dp[amount]

时间复杂度O(mn),空间复杂度O(n)

原文地址:https://www.cnblogs.com/xxxxxiaochuan/p/13063591.html