就是说,假如给你若干枚不同面值的硬币,然后再给你一个值,问用最少的硬币数来加起来得到这个数字。
下面直接看题目(看了九章算法的课进行总结)
比如给的例1
我们可以知道,最后一枚硬币一定是1或2或5(没问题吧!)
在这里我们开一个数组f来表示方法数
那么我们的主要问题就是要求解出前面的f[11 - 1] or f[11 - 2] or f[11 - 5]中最小的那 个,变换为求解之前的子问题,因为最后一枚就是1个硬币。
所以f[11] = Min{ f[11 - 1] , f[11 - 2] , f[11 - 5] }。
初始条件f [0] = 0 (0元当然有0中可能。。。)其他的都设置为正无穷
我们从f [1] f [2] f [3]往后算,因为这样的话前面的都在之前算过了。比如说 f [11] = Min{ f[11 - 1] , f[11 - 2] , f[11 - 5] } ,在这里,f [10] f [9] f [6 ] 之前都算过了。
由于输入的值是一个数组以及最大的值M,在这里定义一个函数coinChange
首先计算一下数组的长度(就是那个输入的几个硬币的那个数字),比如example中的1 2 5 ,长度就是3,接着初始化f [0] = 0,接下来写两重循环,用来计算 f
public class A{
public int coinChange(int[] A,int M)
{
int n = A.length;
// 初始化一个数字,长度给M+1,因为我们下面写的话下标从1开始遍历
int[] f = new int[M + 1];
//初始条件f[0] = 0
f[0] = 0;
//两重循环
for (int i = 1; i <= M; i ++){
//首先全部设置为无穷大
f[i] = Integer.MAX_VALUE;
// 下面的循环用来取那个上文中提到的min
for (int j = 0; j < n; j ++){
// 硬币的大小要小于那个值 && min的条件 && 不是无穷
if (A[j] <= i && f[i - A[j]] + 1 < f[i] && f[i - A[j]] != Integer.MAX_VALUE){
// 更新f[i]的值,让它取到最小值
f[i] = f[i - A[j]] + 1;
}
}
}
// 到最后进行判断
if (f[M] == Integer.MAX_VALUE){
return -1;
}else{
return f[M];
}
}
}