我们先观察第一个问题,问题中的黑体字是最少的硬币个数。
如果令dp[i]是组合成金额i需要的最少硬币个数,那么很显然dp[i]=min(1+dp[i-c]),其中c是任意一个硬币的值。也就是说,最终用到的硬币个数,应当是一个面值为c的,加上总金额i-c对应的硬币个数。
代码如下
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
coins.sort()
MAX_INT=0x7fffffff
dp=[MAX_INT]*(amount+1)
dp[0]=0
for i in range(1,len(dp)):
for c in coins:
if i<c:
break
else:
dp[i]=min(dp[i],dp[i-c]+1)
return -1 if dp[-1]==MAX_INT else dp[-1]
再来观察这个问题
我们假设dp[i][j]表示前i中硬币能够组合出总金额为j的组合数,那么很容易看出
dp[i][j]=dp[i-1][j]+dp[i-1][j-c]+dp[i-1][j-2*c]+....+dp[i-1][j-k*c]
其中c是第i个硬币的面值,这分别对应了取0个,1个...k个。
并且注意到
dp[i][j-c]=dp[i-1][j-c]+dp[i-1][j-2*c]+dp[i-1][j-3*c]+....+dp[i-1][j-k*c]
也就是说
dp[i][j]=dp[i-1][j]+dp[i][j-c]
去掉一维就是
dp[j]=dp[j]+dp[j-c]
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
dp=[0]*(amount+1)
dp[0]=1
coins.sort()
for c in coins:
for i in range(c,len(dp)):
dp[i]+=dp[i-c]
#print(dp)
return dp[-1]