0722更新
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
dp = [1] + [0 for _ in range(amount)]#储存每种面值的凑数种类
for coin in coins:
#逐个考察每一种面额
#即 一开始只考察一种面额
#而后 慢慢增加面额的种类
if coin > amount:
#如果是超大面额 它自己一张都超过了amount
#不可能对结果产生贡献 跳过
continue
#对于这个面额以上直到amount的每一种可能的总金额 i
for i in range(coin,amount+1):
dp[i] += dp[i-coin]
#新考察coin以后 则i的数目可以认为是i-coin的数目
return dp[amount]
将coins升序排列后 二阶dp
dp[i][j]的含义是
总金额i用coins[j:]中的面值来凑的话
能有几种
dp[i][j] = dp[i-coin[j]][j] + dp[i][j+1]
含义是 总金额i用coins[j:]中的面值来凑的种数
等价于
总金额i-coin[j]后用coins[j:]中的面值来凑(即拿了一张coin[j]用)
+
总金额i用coins[j-1:]中的面值来凑(尝试多考虑一种面值)
其中当i-coin[j] 小于0 或 j+1超出范围时 对应项取0
class Solution:
def __init__(self):
self.res = []
def change(self, amount: int, coins: List[int]) -> int:
if coins == []:
return 1 if amount == 0 else 0
if amount == 0:
return 1
coins = sorted(coins)
nums_coins = len(coins)
self.res.append([1 for _ in range(nums_coins)])
for _ in range(1,amount+1):
self.res.append([0 for _ in range(nums_coins)])
min_coin = coins[0]
for i in range(min_coin,amount+1):
for j in range(nums_coins-1,-1,-1):
tempA = 0 if i-coins[j] < 0 else self.res[i-coins[j]][j]
tempB = 0 if j + 1 >= nums_coins else self.res[i][j+1]
#print(self.res)
self.res[i][j] = tempA + tempB
return self.res[-1][0]#if self.res[-1][0] != -1 else 0