【补充题目】
给定数组arr,arr中所有的值都为正数。每个值仅代表一张钱的面值,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数。
【举例】
arr=[5,2,3],aim=20
5元、2元和3元的钱各有1张,所以无法组成20元,默认返回-1.
arr=[5,2,5,3],aim=10
5元的货币有2张,可以组成10元,且该方案所需张数最少,返回2.
arr=[5,2,5,3],aim=15
所有的钱加起来才能组成15元,返回4
arr=[5,2,5,3],aim=0
不用任何货币就可以组成0元,返回0
【代码】
public static void main(String[] args) {
int[] m={5,2,3};
int[] n={5,2,5,3};
//方法1
System.out.println(minCoins3(m,20));//-1
System.out.println(minCoins3(n,10));//2
System.out.println(minCoins3(n,15));//4
System.out.println(minCoins3(n,0));//0
//方法2
System.out.println(minCoins4(m,20));//-1
System.out.println(minCoins4(n,10));//2
System.out.println(minCoins4(n,15));//4
System.out.println(minCoins4(n,0));//0
}
//换钱的最小货币数_补充题目
public static int minCoins3(int[] arr,int aim){
if(arr==null||arr.length==0||aim<0){
return -1;
}
int n=arr.length;
int[][] dp=new int[n][aim+1];
int max=Integer.MAX_VALUE;
//dp第一行,只使用一张arr[0],有dp[0][arr[0]]=1,其他为max
for(int j=1;j<=aim;j++){
dp[0][j]=max;
}
if(arr[0]<=aim){
dp[0][arr[0]]=1;
}
int leftup=0;//左上角某个位置的值
for(int i=1;i<n;i++){
for(int j=1;j<=aim;j++){
leftup=max;
if(j-arr[i]>=0 && dp[i-1][j-arr[i]]!=max){
leftup=dp[i-1][j-arr[i]]+1;
}
dp[i][j]=Math.min(leftup, dp[i-1][j]);
}
}
return dp[n-1][aim]!=max?dp[n-1][aim]:-1;
}
//方法2
public static int minCoins4(int[] arr,int aim){
if(arr==null||arr.length==0||aim<0){
return -1;
}
int n=arr.length;
int max=Integer.MAX_VALUE;
int[] dp=new int[aim+1];
for(int j=1;j<=aim;j++){
dp[j]=max;
}
if(arr[0]<=aim){
dp[arr[0]]=1;
}
int leftup=0;
for(int i=1;i<n;i++){
for(int j=aim;j>0;j--){
//for(int j=1;j<=aim;j++){ 就不对!
leftup=max;
if(j-arr[i]>=0 && dp[j-arr[i]]!=max){
leftup=dp[j-arr[i]]+1;
}
dp[j]=Math.min(leftup, dp[j]);
}
}
return dp[aim]!=max?dp[aim]:-1;
}