[NC126]换钱的最少货币数(Java实现)

本文介绍了一种利用动态规划解决给定正整数数组和目标金额找零问题的方法。通过排序数组,定义dp数组并逐步填充,找到组成目标金额所需的最少货币数量。关键代码实现和示例清晰展示了算法过程。

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

示例

输入:[5,2,3],20

返回值:4,最少需要四张5才能组成20

输入:[5,2,3],0

返回值:0,可以一张不取。

输入:[3,5],2

返回值:-1,没办法组成2

思路:使用一个dp数组存放组成每一面值的最少货币数,数组大小为aim+1,dp数组初始值全为-1;

以[5,2,3],20为例。

初始化数组,int[] dp = new int[21];:

        dp[0]=0;

        dp[2]=1;

        dp[3]=1;

        dp[5]=1;

然后根据初始值逐个给dp[i]赋值

dp[1]=min{dp[-4]+1,dp[-1]+1,dp[-2]+1},因为dp[-1],dp[-2],dp[-4],都不存在,所以dp[1]的值无法更新,还是-1,即无法组成面值为1的情况。

dp[4]=min{dp[-1]+1,dp[2]+1,dp[1]+1},因为dp[-1]不存在,dp[1]=-1,所以只有dp[2]一个有效值,更新dp[4]=dp[2]+1=2

dp[6]=min{dp[1]+1,dp[4]+1,dp[3]+1},因为dp[1]=-1,所以有dp[3]、dp[4]两个有效值,更新dp[6]=min{1+1,2+1}=2;

dp[7]=min{dp[2]+1,dp[5]+1,dp[4]+1},dp[2]、dp[5]、dp[4]均为有效值,所以更新dp[7]=min{1+1,1+1,2+1}=2。

之后依此类推,直到计算出dp[aim];

注意!!!也就是说,只有当dp[i]的下标i有效(i>=0)且dp[i]!=-1时,才是有效值,才可以更新数据。
   

代码实现:

import java.util.*;


public class Solution {
    /**
     * 最少货币数
     * @param arr int整型一维数组 the array
     * @param aim int整型 the target
     * @return int整型
     */

    public int minMoney (int[] arr, int aim) {
        // write code here
        Arrays.sort(arr);
        if(aim==0){
            return 0;
        }else if(arr.length==0||arr==null||aim<arr[0]){
            return -1;
        }
        int[] dp = new int[aim+1];
        for(int i=0;i<dp.length;i++){
            dp[i]=-1;
        }
        dp[0]=0;
        for(int i=0;i<arr.length;i++){
            dp[arr[i]]=1;
        }
        
        for(int i=0;i<dp.length;i++){
            if(dp[i]==-1){
                for(int j=0;j<arr.length;j++){
                    if(i-arr[j]>=0 && dp[i-arr[j]]!=-1){
                        if(dp[i]==-1){
                            dp[i] =dp[i-arr[j]]+1;
                        }else{
                            dp[i] = Math.min(dp[i-arr[j]]+1,dp[i]);
                        }
                    }
                }
            }
        }
       
        return dp[aim];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值