【问题标题】:Unique Ways To Give Change- Not Outputting Expected Values给予改变的独特方式——不输出期望值
【发布时间】:2020-05-30 02:52:45
【问题描述】:

我正在尝试创建一个程序,该程序仅使用递归和常量内存(因此没有循环)输出所有可能的独特方式来对给定输入进行更改。

对于 25 美分的金额,它应该按以下示例格式打印出所有可能的组合:

0*25+0*10+1*5+20*1
0*25+0*10+2*5+15*1
etc..

其中 0* 是用作示例的季度数 (25)

我的程序的问题是它只打印出来:

0=0*25+0*10+0*5+25*1+

而不是其余的组合。我怀疑这是因为我弄乱了 printCombinations 和 getLargerCombinations 方法(它们基本上是模拟 for 循环的递归方法),但我不知道问题出在哪里。

这是整个代码:

public class HW {

    static int[] coins = {25,10,5,1};
    static int[] counts = new int[coins.length];


    static void getCombinations(int[] counts, int startIndex, int totalAmount) {
        if(startIndex>= coins.length) {
            System.out.print(""+totalAmount+"=");
            printCombinations(0);
            return;
        }

        if(startIndex == coins.length - 1) {

            if(totalAmount%coins[startIndex]==0) //good combo 
            {
                //setting count of coins at start index
                counts[startIndex] = totalAmount/coins[startIndex];
                //move on to recursive calls
                getCombinations(counts, startIndex + 1, 0);
            }
        }

        else //still need to choose 0-N larger coins
        {
            getLargerCoins(0, totalAmount, startIndex);

        }


    }

    //Prints out all the possible combinations of change
    static void printCombinations(int i) {
        if(i >= coins.length) {
            System.out.print("\n");
            return;
        }
        System.out.print("" + counts[i] + "*" + coins[i] + "+");
        printCombinations(++i);
    }



    static void getLargerCoins(int j, int totalAmount, int startIndex) {
        if(j >= totalAmount/coins[startIndex]) {
            return;
        }
        //for every cycle in the loop, we choose an arbitray # of larger coins and proceed next
        counts[startIndex] = j;
        getCombinations(counts, startIndex+1, totalAmount-coins[startIndex]*j);
        j++;
    }

    public static void main(String[] args) {
        getCombinations(counts, 0, 25);
    }



}

****编辑:*****

在 getLargerCoins 方法下,我只是迭代了 j++,但忘记调用 getLargerCoins 方法来继续递归。通过写作修正了这一行:

getLargerCoins(++j, totalAmount, startIndex);

运行程序时的输出:

0=0*25+0*10+0*5+25*1+
0=0*25+0*10+1*5+20*1+
0=0*25+0*10+2*5+15*1+
0=0*25+0*10+3*5+10*1+
0=0*25+0*10+4*5+5*1+
0=0*25+1*10+0*5+15*1+
0=0*25+1*10+1*5+10*1+
0=0*25+1*10+2*5+5*1+

但是,它仍然没有输出所有可能的组合

【问题讨论】:

  • 你试过调试你的代码吗?
  • 它不会导致意外结果,但将counts 传递给每个方法调用是没有意义的,它是一个静态类字段,无论如何都可以从所有方法访问。
  • 当你第一次调用 printCombination 时,你会用你的 return 语句结束递归。

标签: java arrays algorithm performance recursion


【解决方案1】:

所有你可以用循环解决的问题,你也可以用递归解决(不是很可读,但可行的解决方案):

public static void printCombinations(int[] coins, int amount) {
    printCombinations(coins, new int[coins.length], amount, 0);
}

private static void printCombinations(int[] coins, int[] counts, int amount, int index) {
    if (amount == 0) {
        print(coins, counts, 0, "");
    } else if (amount > 0) {
        printCombinationsLoop(coins, counts, amount, index);
    }
}

private static void printCombinationsLoop(int[] coins, int[] counts, int amount, int index) {
    counts[index]++;
    printCombinations(coins, counts, amount - coins[index], index);
    counts[index]--;
    if (index + 1 < coins.length)
        printCombinationsLoop(coins, counts, amount, index + 1);
}

private static void print(int[] coins, int[] counts, int index, String s) {
    if (counts[index] > 0) {
        if (!s.isEmpty())
            s += "+";
        s += counts[index] + "*" + coins[index];
    }
    if (index + 1 == coins.length)
        System.out.println(s);
    else
        print(coins, counts, index + 1, s);
}

硬币应该是唯一的才能正常工作。

【讨论】:

    【解决方案2】:

    是什么让您认为递归比循环消耗更少的内存?

    只有递归和常量内存(所以没有循环)。

    对于你的问题,我认为迭代更简单更快。

    public class MyClass {
      public static void main(String args[]) {
    
        int[] coins = {25,10,5,1};
        int[] counts = {0,0,0,0};
    
        long recStart = System.currentTimeMillis();
        recursive(25,0,coins,counts);
        long recEnd = System.currentTimeMillis();
        System.out.println("recursive millis: "+( recEnd- recStart));
    
        long iterativeStart = System.currentTimeMillis();
        iterative(25);
        long iterativeEnd = System.currentTimeMillis();
        System.out.println("iterative millis: "+( iterativeEnd- iterativeStart));
    
    }
    
    public static void recursive(int restValue, int level, int[] coins, int[] counts){
        if(restValue==0){
           System.out.println(counts[0]+"*25+"+counts[1]+"*10+"+counts[2]+"*5+"+counts[3]+"*1"); 
        }else if(restValue>0 && level<4){
            for(int i = 0; i<= restValue/coins[level]; i++ ){
                 int rest= restValue - ( i*coins[level] );
                 counts[level]=i;
                 recursive(rest,level+1,coins,counts);
            }
        }
    }
    
    public static void iterative(int desiredValue){
        int q1=25;
        int q2=10;
        int q3=5;
    
        for(int i1 = 0; i1<= desiredValue/q1; i1++ ){
            int rest1= desiredValue - ( i1*q1 );
    
            for(int i2 = 0; i2<= rest1/q2; i2++ ){
                int rest2= rest1 - ( i2*q2 );
                for(int i3 = 0; i3<= rest2/q3; i3++ ){
                    int rest3= rest2 - ( i3*q3 );
                    System.out.println(i1+"*25+"+i2+"*10+"+i3+"*5+"+rest3+"*1");
                }
            }
        }
    }
    

    }

    【讨论】:

    • 这只是问题的规范,我不允许使用任何循环实例,只能使用递归解决
    • 对于递归方法的 else 块中的循环,我制作了一个递归函数来尝试模拟您的循环。可以看看好不好?repl.it/repls/FairFixedLocations
    猜你喜欢
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多