有点难理解,其实还是递归,https://www.jianshu.com/p/b9d7ff91684e
i: 代表可以使用的货币种类为 arr[0..i]
j: 代表需要兑换的面值数,其取值范围为[0..aim],因此实现时,二维数组的列数应该为aim + 1
对于dp[i][j],更新的依据有两个值,一个是“不使用当前种类的货币时,组成总数的j的最小方法,即dp[i-1][j]”,另外一个是“使用并且仅使用一张当前种类的货币时,组成总数的j的最小方法,即 dp[i][j-arr[i]] + 1”,取这两个值中的最小值即为dp[i][j]的值。
上面的实现,需要的空间复杂度是O(N * aim),下面的方法,可以将空间复杂度优化到O(aim)。
优化方法:
生成一个一维动态规划数组dp[aim + 1]
构造初始值:参考上面的方法,初始值表示只使用arr[0]一种货币时,兑换[0..aim]的最少货币数。
更新动态规划表:更新方向,从左到右更新。对于dp[j],更新的依据有两个,一个是 dp[j](old),换算成二维数组,即为不使用arr[j]货币时的最少货币数,即为dp[line-1][j]。另外一个是dp[j-arr[j]] + 1,即为“使用并且仅使用一张当前种类的货币时的最少货币数”,换算成二维数组,即为dp[line][j-arr[j]] + 1.
# # 最少货币数 # @param arr int整型一维数组 the array # @param aim int整型 the target # @return int整型 # class Solution: def minMoney(self, arr, aim): # write code here N=len(arr) dp = [float('inf')]*(aim+1) dp[0] = 0 for i in range(1, aim+1): for j in range(N): if i < arr[j]: continue dp[i] = min(dp[i], dp[i-arr[j]]+1) if dp[aim] == float('inf'): return -1 else: return dp[aim]