原题
给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。
如果无解,请返回-1.
数据范围:数组大小满足 0 \le n \le 100000≤n≤10000 , 数组中每个数字都满足 0 < val \le 100000<val≤10000,0 \le aim \le 50000≤aim≤5000
要求:时间复杂度 O(n \times aim)O(n×aim) ,空间复杂度 O(aim)O(aim)。
输入示例:
[5,2,3],20
输出示例:
4
核心转移方程:
F[v] = min(F[v − Wi])+1
方程就一个意思,v元的组合,可以划分为,按照每种面值的钱都减少一张Wi,v-Wi元的最优解,最后再补上减少的一张钱即可得到最终答案
基本实现用递归即可,初始化最小面额之下的最优组合即可,不是0就是-1
需要关注的点:
1、如果面额减少一张以后,v-Wi 为负数,则跳过该种情况
2、如果 F[v − Wi] 为负数,则跳过该种情况,因为没有合法情况
3、在遍历完所有面值的情况,没有合法情况,即返回-1
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 最少货币数
# @param arr int整型一维数组 the array
# @param aim int整型 the target
# @return int整型
#
class entity:
def __init__(self,N:int) -> None:
self.F = [-1 for i in range(N+1)]
self.F[0] = 0
pass
pass
class Solution:
def minMoney(self , arr: List[int], aim: int) -> int:
# write code here
result = entity(aim)
if len(arr)==0:
return -1
minValue = min(arr)
for iterNum in range(1,aim+1):
if iterNum<minValue:
# 小于最小面额时 全部都是-1
result.F[iterNum]=-1
pass
else:
# 大于最小面额时 利用递归公式
# F[n] = min(F[n-arr[j]]) + 1
F_tmp_list = []
for item in arr:
aim_temp = iterNum-item
if aim_temp<0:
continue
F_temp = result.F[aim_temp]
if F_temp>=0:
F_tmp_list.append(F_temp)
pass
if len(F_tmp_list)>0:
result.F[iterNum]=min(F_tmp_list)+1
else:
result.F[iterNum] = -1
pass
pass
return result.F[aim]
标签:总结,arr,int,Wi,aim,零钱,算法,result,pass
From: https://www.cnblogs.com/dengliang356a/p/17469759.html