换钱的最少货币数

举报
程序员学长 发表于 2022/02/11 14:16:28 2022/02/11
【摘要】 换钱的最少货币数读前福利322. 零钱兑换 问题描述给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。如果无解,请返回-1.示例:输入:coins = [1, 2, 5],amount = 11输出:3说明:11 = 5 + 5 + 1 分析问题由于题目是求最优解问题,所以...

换钱的最少货币数

读前福利

322. 零钱兑换

问题描述

给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。如果无解,请返回-1.

示例:

输入:coins = [1, 2, 5],amount = 11

输出:3

说明:11 = 5 + 5 + 1

分析问题

由于题目是求最优解问题,所以我们最直观的感觉就是这题是否可以使用动态规划来求解。

我们都知道,对于求解动态规划相关的问题,最重要的就是求出状态转移方程。下面我们来看一下如何求解,首先我们定义F(S) 为组成金额 S 所需的最少货币数量。

假设目前我们已经知道了F(S),和最后一枚货币的面值是C,我们就可以得出:

F(S)=F(S-C)+1

由于最后一枚货币的面值是未知的,所以我们需要枚举每个货币的面额值 C0, C1,…,Cn-1,并选择其中的最小值。即

F(S)=min {F(S-C0) ,F(S-C1),F(S-C3),....,F(S-Cn-1)} + 1
S-Ci >=0
当S=0时,F(S)=0
当n=0时,即货币的种类为0时,F(S)无解,即F(S)=-1

所以,F(S)的状态转移方程为

F(S)=min {F(S-C0) ,F(S-C1),F(S-C3),....,F(S-Cn-1)} + 1

其中 Cj 代表的是第 j 枚货币的面值,即我们枚举最后一枚货币面额是Cj,那么F(S)需要从S-Cj这个金额对应的状态 F(S-Cj) 转移过来,再加上枚举的这枚货币数量1的贡献。由于题目是求货币的数量最少,所以 F(S)为前面能转移过来的状态的最小值。

假设 coins= [1, 2, 5],amount = 11,即F(11) = min( F(10), F(9), F(6) ) + 1。

image-20211118171456070

下面我们来看一下代码的实现。

import sys
class Solution:
    def coinChange(self, coins,amount):
        dp = [sys.maxsize] * (amount + 1)

        #S0时,需要的货币数为0
        #S<0时,直接忽略dp[S]
        dp[0] = 0
        for coin in coins:
            #忽略S<0的。
            for x in range(coin, amount + 1):
                dp[x] = min(dp[x], dp[x - coin] + 1)
        return dp[amount] if dp[amount] != sys.maxsize else -1

该算法的时间复杂度是O(Sn),其中S是金额数,n是不同面额的个数。空间复杂度是O(S)。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。