算法题总结-找零钱

原题

给定数组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]
posted @ 2023-06-09 17:10  356a  阅读(18)  评论(0编辑  收藏  举报