需要帮助修复动态编程代码/使用Java计算最小硬币递归代码吗

需要帮助修复动态编程代码/使用Java计算最小硬币递归代码吗,java,recursion,dynamic-programming,backtracking,Java,Recursion,Dynamic Programming,Backtracking,我这里有我的代码,它的目的是返回硬币的最小配置,以便对给定的金额进行更改。它有两个参数,sum和面值列表。我没有编译错误,程序可以提供输出,但我得到的结果并不完全正确。非常感谢您在这方面的任何帮助 //this program calculates the minimum coins and distribution of //denominations required to make change for a given sum import java.util.*; import java

我这里有我的代码,它的目的是返回硬币的最小配置,以便对给定的金额进行更改。它有两个参数,sum和面值列表。我没有编译错误,程序可以提供输出,但我得到的结果并不完全正确。非常感谢您在这方面的任何帮助

//this program calculates the minimum coins and distribution of
//denominations required to make change for a given sum
import java.util.*;
import java.io.*;
public class MinCoinCollectionBacktrack {
   private int sum;
   private List<Integer> coins;

   //constructor that takes sum and list of denominations
   //such as [1,5,10,25]
   public MinCoinCollectionBacktrack(int amount,List<Integer> denominationList) {
      sum=amount;
      coins=denominationList;
  }

  //calculate the minimum coins
  //uses map to store sum-->list of combinations
  //eg 3-->[2,1], 4 -->[2,2] for a given denomination list of [1,2,5]
  public  List<Integer> Mincoins() {
   Map<Integer, List<Integer>> lenChoices=new HashMap<Integer,List<Integer>>();
      int maxdenomination=Collections.max(coins);
      Integer sum1= new Integer(sum);
   return minCoins(lenChoices,sum,maxdenomination);

  }

  //wrapper method for MinCoins, it takes a map and updates as when
  //minimum configuration of a sum is found. stores the value
  //as described above
  private List<Integer> minCoins(Map<Integer, List<Integer>> lenChoices, int value,int maxdenomination) {
  //check if sum is a key in map, then return its value
   if (lenChoices.containsKey(value)) {
      return lenChoices.get(value);
  //check if the coinlist contains sum, if yes, it creates a
  //new key value pair to the Map
   } else if (coins.contains(value)) {
      List<Integer> newlist = new ArrayList<Integer>();
      newlist.add(value);
      lenChoices.put(value,newlist);
      return lenChoices.get(value); 
  //if the denomiation is > sum, just return empty list        
   } else if (maxdenomination > value) {
      List<Integer> newlist = new ArrayList<Integer>();
      lenChoices.put(value,newlist);
      return lenChoices.get(value);
  //here is where recursive backtracking happens    
   } else {
      int minLength=0;
      List<Integer> minConfig=new ArrayList<Integer>();
      for (int coin : coins) {
         List<Integer> results = minCoins(lenChoices,value - coin,maxdenomination);
         if (!results.isEmpty()) {
            if (minLength==0 || (1+results.size()) < minConfig.size()) {               
               results.add(coin);
               minConfig=results;
               minLength=minConfig.size();
            }
         }
     }    
     lenChoices.put(value,minConfig);  
     return lenChoices.get(value);
  }
}

public static void main(String[] args) {
   System.out.println("enter the denoninations, hit enter to Zero(0) to finish");
   Scanner console = new Scanner(System.in);
   List<Integer> coinlist= new ArrayList<Integer>();
   int input = console.nextInt();
   while (input>0) {
      coinlist.add(input);
      input = console.nextInt();
   }
   System.out.println("coin collections are :"+ coinlist);
   System.out.println("enter the sum for which you need minimum coins");
   input = console.nextInt();
   MinCoinCollectionBacktrack result=new MinCoinCollectionBacktrack(input,coinlist);
   List<Integer> output = result.Mincoins();
   System.out.println("you require " + output.size() + " coins in the"
                                    + " following combination " + output);

 } 

} 
//此程序计算最小硬币数和硬币的分配
//对给定金额进行更改所需的面额
导入java.util.*;
导入java.io.*;
公共类MinCoinCollectionBacktrack{
私人整数和;
私人名单硬币;
//构造函数,它接受面额的总和和列表
//例如[1,5,10,25]
公共MinCoinCollectionBacktrack(整数金额、列表面额列表){
总和=金额;
硬币=面额表;
}
//计算最小硬币数
//使用映射存储组合的总和-->列表
//例3-->[2,1],4-->[2,2]对于给定的面额列表[1,2,5]
公开名单{
Map lenChoices=newhashmap();
int MAXDENSION=集合最大值(硬币);
整数sum1=新整数(和);
返回最小硬币(lenChoices、sum、Max面值);
}
//对于MinCoins的包装器方法,它会获取一个地图并根据需要进行更新
//找到总和的最小配置。存储该值
//如上所述
私有列表minCoins(地图选项、整数值、整数最大面额){
//检查sum是否是map中的键,然后返回其值
if(lenChoices.containsKey(值)){
返回lenChoices.get(值);
//检查coinlist是否包含sum,如果是,则创建一个
//映射的新键值对
}否则,如果(硬币包含(价值)){
List newlist=newarraylist();
添加(值);
lenChoices.put(值,newlist);
返回lenChoices.get(值);

//如果表示为>求和,只需返回空列表 }else if(最大面额>值){ List newlist=newarraylist(); lenChoices.put(值,newlist); 返回lenChoices.get(值); //这里是递归回溯发生的地方 }否则{ int minLength=0; List minConfig=new ArrayList(); 用于(整型硬币:硬币){ 列表结果=最小硬币(lenChoices、value-coin、MaxNomination); 如果(!results.isEmpty()){ 如果(minLength==0 | |(1+results.size())0){ 添加(输入); input=console.nextInt(); } System.out.println(“硬币收藏为:“+硬币列表”); System.out.println(“输入需要最少硬币的金额”); input=console.nextInt(); MinCoinCollectionBacktrack结果=新的MinCoinCollectionBacktrack(输入,coinlist); 列表输出=result.Mincoins(); System.out.println(“您需要”+output.size() +“以下组合”+输出); } }

请随意评论在风格和算法方面可能需要改进的地方。谢谢

一般来说,您的代码非常复杂!我尝试了一些更改,如果我正确地理解了您要做的事情,只需几行新行就足以获得正确的值。当然,我还没有尝试过所有可能的组合,所以欢迎你给我一个打破结果的组合

Mincoins方法:

  public  List<Integer> Mincoins() {
    Map<Integer, List<Integer>> lenChoices=new HashMap<Integer, List<Integer>>();
    Collections.sort(coins, Collections.reverseOrder()); // since later on in the code you are iterating over your coins, it makes sense to sort them with the largest first so that you are slowly left with the bits that can not be divided by the larger values and have more probability to be caught be the small ones
    int maxdenomination=Collections.max(coins);
    Integer sum1= new Integer(sum);
    List<Integer> result = new ArrayList<Integer>();
    for (Integer c: coins) { //as per  Nishant Shreshth's comment, you need to check all invalid coins first and don't bother unless one which produces results is found
      println(c);
      result = minCoins(lenChoices, sum, c, 0);
      lenChoices.clear();
      if (result.size() > 0) break;
    }
    return result;
  }
public List Mincoins(){
Map lenChoices=newhashmap();
Collections.sort(coins,Collections.reverseOrder());//由于稍后在代码中您将迭代您的硬币,因此有必要先对它们进行最大排序,这样您就可以慢慢地保留不能除以较大值的位,并且更有可能捕获较小的位
int MAXDENSION=集合最大值(硬币);
整数sum1=新整数(和);
列表结果=新建ArrayList();
对于(整数c:coins){//根据Nishant Shrishth的评论,您需要首先检查所有无效的硬币,除非找到一个产生结果的硬币,否则不要麻烦
println(c);
结果=minCoins(lenChoices,sum,c,0);
lenChoices.clear();
如果(result.size()>0)中断;
}
返回结果;
}
minCoins方法@else{

else {
      int minLength=0;
      List<Integer> minConfig=new ArrayList<Integer>();
      for (int coin : coins) {
        List<Integer> results = minCoins(lenChoices, value - coin, maxdenomination);
        if (!results.isEmpty()) {
          if (minLength==0 || (1+results.size()) < minConfig.size()) {               
            results.add(coin);
            minConfig=results;
            minLength=minConfig.size();
          }
          break; // If we already have a result we don't need to look for the rest of the coins!
        }
      }    
      lenChoices.put(value, minConfig);  
      return lenChoices.get(value);
    }
else{
int minLength=0;
List minConfig=new ArrayList();
用于(整型硬币:硬币){
列表结果=最小硬币(lenChoices、value-coin、MaxNomination);
如果(!results.isEmpty()){
如果(minLength==0 | |(1+results.size())
你真的需要映射吗?你知道这个问题的D.P方程了吗?你没有正确地实现递归方程。请看这里:。//如果表示法是>求和,只返回空列表。你的代码在这里将返回空列表,用于以下输入:硬币:{1,2,5,10,20,501005001000}值:150您的结果:空列表;预期结果:{50100}这就是我的代码的用途:空列表用于在地图中查找。这意味着1000的组合不能形成150的预期结果,这就是为什么我将其分配给空列表1000-->[],其中为50-->[3]。我可能也错了。请