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

被折叠的 条评论
为什么被折叠?



