Python换钱的最少货币数

题目:

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

例:

arr = [5, 2, 3],aim = 20,arr中组成20的最少张数为4,返回4。

arr = [5, 2, 3],aim = 0,不用任何货币就可以组成0,返回0。

arr = [3, 5],aim = 2,钱找不开返回-1 。

思路:

假设arr = [5, 2, 3],aim=10。

建立一个N*(M+1)的矩阵dp,N为arr里的个数,M=aim,dp[i][j]表示由当前行及该行上面所有行的货币种类兑换该列值的最少货币数,所在的列即需要兑换的钱数,dp初始化如下:

行\列012345678910
500000000000
200000000000
300000000000

首先,计算第一行可兑换的钱数,即用5能兑换的钱数,其它不可兑换的钱数用max表示,如下:

行\列012345678910
50maxmaxmaxmax1maxmaxmaxmax2
2           
3           

计算其它位置。对于dp[i][j],当前i行兑换j钱数时,m为i行对应的货币值,若dp[i][j]可以兑换开,则dp[i][j-m]位置也可以兑换,此时dp[i][j] = dp[i][j-m] + 1。同时需要对比上一行兑换该钱数使用的货币数,即dp[i-1][j]的值,取两者的最小值,即为最少货币数。用这个方法处理第二行,前两行显示如下:

行\列012345678910
50maxmaxmaxmax1maxmaxmaxmax2
20max1max2132432
3           

用同样的方法处理第三行,如下:

行\列012345678910
50maxmaxmaxmax1maxmaxmaxmax2
20max1max2132432
30max112122232

代码:

 使用python实现上面的过程,如下:

import sys

def min_coins(arr, aim):
    if arr==None or len(arr)==0 or aim<0:
        return -1
    n = len(arr)
    max = sys.maxsize
    dp = [[0]*(aim+1) for i in range(n)]
    for j in range(1, aim+1):
        dp[0][j] = max
        if (j-arr[0])>=0 and dp[0][j-arr[0]]!=max:
            dp[0][j] = dp[0][j-arr[0]] + 1
    for i in range(1,n):
        for j in range(1, aim+1):
            temp = max
            if (j-arr[i])>=0 and dp[i][j-arr[i]]!=max:
                temp = dp[i][j-arr[i]] + 1
            dp[i][j] = min(temp, dp[i-1][j])
    return dp[n-1][aim] if dp[n-1][aim]!=max else -1

输入arr和aim,调用上面的方法查看结果:

arr = [5, 2, 3]
aim = 10
res = min_coins(arr, aim)
print('换钱的最少货币数为:', res)

结果如下:

换钱的最少货币数为: 2

 若要查看dp矩阵的元素,可在输出前打印,或者同最少货币数一起返回。

 

参考:《程序员代码面试指南》左程云

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值