Java 打印最小更改算法中使用的面额时出现问题
所以我写了一个递归算法来解决这个问题,计算出一组特定面额的最小数量的“硬币”可能达到一个给定的总和。这个算法似乎是可行的,但因为它是递归的,并且在选择一个或另一个选项之前会计算所有可能的选项,所以我很难想出一种方法来打印出所使用的面额。因此,基本上我可以计算出可能使用的最少数量的硬币,但不能计算它们是哪种硬币。这是我用来驱动它的代码和主要方法。任何关于简化算法本身的建议都将受到欢迎Java 打印最小更改算法中使用的面额时出现问题,java,dynamic,recursion,dynamic-programming,coin-change,Java,Dynamic,Recursion,Dynamic Programming,Coin Change,所以我写了一个递归算法来解决这个问题,计算出一组特定面额的最小数量的“硬币”可能达到一个给定的总和。这个算法似乎是可行的,但因为它是递归的,并且在选择一个或另一个选项之前会计算所有可能的选项,所以我很难想出一种方法来打印出所使用的面额。因此,基本上我可以计算出可能使用的最少数量的硬币,但不能计算它们是哪种硬币。这是我用来驱动它的代码和主要方法。任何关于简化算法本身的建议都将受到欢迎 public class DynamicCoinChange { public static void
public class DynamicCoinChange {
public static void main(String[] args) {
int[] denoms = {1, 6, 10, 25};
int numCoins = dynamicCoinChange(denoms, 18, 3);
System.out.println(numCoins);
}
public static int dynamicCoinChange(int[] denoms, int amt, int start) {
if (amt == 0 || start < 0) {
return 0;
} else if (amt == 1) {
return 1;
} else if (denoms[start] > amt ||
dynamicCoinChange(denoms, amt, start-1) <
(1 + dynamicCoinChange(denoms, amt-denoms[start], start)) &&
!(dynamicCoinChange(denoms, amt, start-1) == 0)) {
return dynamicCoinChange(denoms, amt, start-1);
} else {
return 1 + dynamicCoinChange(denoms,amt-denoms[start], start);
}
}
}
公共类动态更改{
公共静态void main(字符串[]args){
int[]denoms={1,6,10,25};
int numCoins=动态变化(denoms,18,3);
System.out.println(numCoins);
}
公共静态int动态inchange(int[]denoms,int amt,int start){
如果(金额==0 | |开始<0){
返回0;
}否则如果(金额==1){
返回1;
}否则如果(denoms[开始]>金额| |
动态变化(起点、金额、起点-1)
(1+动态增量变化(增量、金额增量[启动]、启动))&&
!(动态增量变化(数据、金额、开始-1)=0){
返回动态更改(denoms、amt、start-1);
}否则{
返回1+dynamiccinchange(denoms,amt denoms[start],start);
}
}
}
最小变化问题不需要递归编程。它可以用一种更简单的迭代方式编程
int[] denoms = { 1, 6, 10, 25 };
int amt = 18;
double[] min = new double[ amt + 1 ];
for( int i = 1; i < min.length; i++ ) { // We're keeping min[ 0 ] as 0/
min[ i ] = Double.POSITIVE_INFINITY;
}
for( int i = 1; i <= amt; i++ ) {
for( int j = 0; j <= N - 1; j++ ) {
if( denoms[ j ] <= i && min[ i - denoms[ j ] ] + 1 < min[ i ] )
min[ i ] = min[ i - denoms[ j ] ] + 1;
}
}
int[]denoms={1,6,10,25};
国际金额=18;
double[]最小值=新的double[amt+1];
对于(inti=1;i 对于(int i=1;i我们需要知道两条信息:
- 当选择硬币作为最佳解决方案时
- 选择哪种硬币作为最佳解决方案
根据您的算法,我们知道无论何时返回1
,我们都会选择一枚硬币。我们还知道,在所选硬币的索引处选择的硬币是start
。因此,我们有解决此问题的信息
由于性能在这里不是问题,我们只需传递一个coins参数,该参数在选择coins时填充
public static int dynamicCoinChange(int[] denoms, int amt, int start, ArrayList<Integer> coins) {
if (amt == 0 || start < 0) {
return 0;
} else if (amt == 1) {
coins.add(1);
return 1;
} else if (denoms[start] > amt
// Note that these calls are not guaranteed to be in our solution
// Thus, we make a copy to prevent the calls from modifying our solution
|| dynamicCoinChange(denoms, amt, start-1, new ArrayList<Integer>(coins)) <
(1 + dynamicCoinChange(denoms, amt-denoms[start], start, new ArrayList<Integer>(coins)))
&& !(dynamicCoinChange(denoms, amt, start-1, new ArrayList<Integer>(coins)) == 0)) {
return dynamicCoinChange(denoms, amt, start-1, coins);
} else {
coins.add(denoms[start]);
return 1 + dynamicCoinChange(denoms,amt-denoms[start], start, coins);
}
}
public static int dynamiccinchange(int[]denoms,int amt,int start,ArrayList coins){
如果(金额==0 | |开始<0){
返回0;
}否则如果(金额==1){
增加(1);
返回1;
}否则如果(denoms[开始]>金额
//请注意,这些调用不一定在我们的解决方案中
//因此,我们制作一个副本以防止调用修改我们的解决方案
||动态更改(denoms、amt、start-1、新阵列列表(硬币))<
(1+dynamiccinchange(denoms,amt denoms[start],start,new ArrayList(硬币)))
&&!(DynamicInchange(denoms、amt、start-1、新阵列列表(硬币))=0){
返回动态更改(denoms、amt、start-1、硬币);
}否则{
硬币。添加(denoms[开始]);
返回1+dynamiccinchange(denoms,amt denoms[start],start,coins);
}
}
由于这需要我们更改方法签名,我们还必须修改驱动程序:
public static void main(String[] args) {
int[] denoms = {1, 6, 10, 25};
ArrayList<Integer> coins = new ArrayList<Integer>();
int numCoins = dynamicCoinChange(denoms, 7, 3, coins);
for (Integer coin : coins)
System.out.println(coin);
System.out.println(numCoins);
}
publicstaticvoidmain(字符串[]args){
int[]denoms={1,6,10,25};
ArrayList硬币=新的ArrayList();
int numCoins=动态变化(德努姆斯,7,3,硬币);
用于(整数硬币:硬币)
系统输出打印(硬币);
System.out.println(numCoins);
}
在递归调用结束时,coins
应该包含按时间顺序选择的硬币列表。我知道这是低效的,但我有点想递归地这样做,因为我喜欢递归哈哈。:/No,这不起作用,因为我们基本上在计算很多可能的解决方案,然后根据co选择一个比较。是的,我知道这是低效的哈哈。如果你去掉倒数第二个条件的后半部分,| | dynamiccinchange(denoms,amt,start-1)<(1+dynamiccinchange(denoms,amt denoms[start],start))&!(dynamiccinchange(denoms,amt,start-1)==0)
这应该还可以。你是说从“| |”开始删除还是从“&&”开始删除?我不确定这一点。因为这样一来,你就不能保证面额小于最大面额是正确的第一选择,即使如此!(denom[start]>amt)你是对的。这组硬币不允许我使用贪婪选择属性。我将我的解决方案修改为伪尾部调用方法。如果不是更糟的话,它应该和你当前的解决方案一样低效。