开发者

Making change recursively: How do I modify my algorithm to print all combinations?

I have an algorithm that recursively makes change in the following manner:

public static int makeChange(int amount, int currentCoin) {

        //if amount = zero, we are at the bottom of a successful recursion
     开发者_如何学C   if (amount == 0){

            //return 1 to add this successful solution
            return 1;           

            //check to see if we went too far
        }else if(amount < 0){

            //don't count this try if we went too far
            return 0;

            //if we have exhausted our list of coin values
        }else if(currentCoin < 0){              

            return 0;

        }else{  

            int firstWay = makeChange(amount, currentCoin-1);
            int secondWay = makeChange(amount - availableCoins[currentCoin], currentCoin);

            return firstWay + secondWay;            
        }       
}   

However, I'd like to add the capability to store or print each combination as they successfully return. I'm having a bit of a hard time wrapping my head around how to do this. The original algorithm was pretty easy, but now I am frustrated. Any suggestions?

CB


Without getting into the specifics of your code, one pattern is to carry a mutable container for your results in the arguments

public static int makeChange(int amount, int currentCoin, List<Integer>results) {
     // ....
     if (valid_result) {
        results.add(result);
        makeChange(...);
     }
     // ....
}

And call the function like this

List<Integer> results = new LinkedList<Integer>();
makeChange(amount, currentCoin, results);
// after makeChange has executed your results are saved in the variable "results"


I don't understand logic or purpose of above code but this is how you can have each combination stored and then printed.

public class MakeChange {

    private static int[] availableCoins = { 
        1, 2, 5, 10, 20, 25, 50, 100 };

    public static void main(String[] args) {
        Collection<CombinationResult> results = makeChange(5, 7);
        for (CombinationResult r : results) {
            System.out.println(
                    "firstWay=" + r.getFirstWay() + " : secondWay="
                    + r.getSecondWay() + " --- Sum=" + r.getSum());
        }
    }

    public static class CombinationResult {

        int firstWay;

        int secondWay;

        CombinationResult(int firstWay, int secondWay) {
            this.firstWay = firstWay;
            this.secondWay = secondWay;
        }

        public int getFirstWay() {
            return this.firstWay;
        }

        public int getSecondWay() {
            return this.secondWay;
        }

        public int getSum() {
            return this.firstWay + this.secondWay;
        }

        public boolean equals(Object o) {
            boolean flag = false;
            if (o instanceof CombinationResult) {
                CombinationResult r = (CombinationResult) o;
                flag = this.firstWay == r.firstWay
                        && this.secondWay == r.secondWay;
            }
            return flag;
        }

        public int hashCode() {
            return this.firstWay + this.secondWay;
        }

    }

    public static Collection<CombinationResult> makeChange(
            int amount, int currentCoin) {
        Collection<CombinationResult> results = 
            new ArrayList<CombinationResult>();
        makeChange(amount, currentCoin, results);
        return results;
    }

    public static int makeChange(int amount, int currentCoin,
            Collection<CombinationResult> results) {
        // if amount = zero, we are at the bottom of a successful recursion
        if (amount == 0) {
            // return 1 to add this successful solution
            return 1;
            // check to see if we went too far
        } else if (amount < 0) {
            // don't count this try if we went too far
            return 0;
            // if we have exhausted our list of coin values
        } else if (currentCoin < 0) {
            return 0;
        } else {
            int firstWay = makeChange(
                amount, currentCoin - 1, results);
            int secondWay = makeChange(
                amount - availableCoins[currentCoin],
                currentCoin, results);
            CombinationResult resultEntry = new CombinationResult(
                firstWay, secondWay);
            results.add(resultEntry);
            return firstWay + secondWay;
        }
    }

}


I used the following:

/**
     * This is a recursive method that calculates and displays the combinations of the coins included in
     * coinAmounts that sum to amountToBeChanged.
     * 
     * @param coinsUsed is a list of each coin used so far in the total.  If this branch is successful, we will add another coin on it.
     * @param largestCoinUsed is used in the recursion to indicate at which coin we should start trying to add additional ones.
     * @param amountSoFar is used in the recursion to indicate what sum we are currently at.
     * @param amountToChange is the original amount that we are making change for.
     * @return the number of successful attempts that this branch has calculated.
     */private static int change(List<Integer> coinsUsed, Integer currentCoin, Integer amountSoFar, Integer amountToChange)
    {
        //if last added coin took us to the correct sum, we have a winner!
        if (amountSoFar == amountToChange)
        {
            //output 
            System.out.print("Change for "+amountToChange+" = ");

            //run through the list of coins that we have and display each.
            for(Integer count: coinsUsed){

                System.out.print(count + " ");
            }
            System.out.println();       

            //pass this back to be tallied
            return 1;
        }

        /*
         * Check to see if we overshot the amountToBeChanged
         */
        if (amountSoFar > amountToChange)
        {
            //this branch was unsuccessful
            return  0;
        }

        //this holds the sum of the branches that we send below it
        int successes=0;

        // Pass through each coin to be used
        for (Integer coin:coinAmounts)
        {
            //we only want to work on currentCoin and the coins after it
            if (coin >= currentCoin)
            {
                //copy the list so we can branch from it
                List<Integer> copyOfCoinsUsed = new ArrayList<Integer>(coinsUsed);

                //add on one of our current coins
                copyOfCoinsUsed.add(coin);

                //branch and then collect successful attempts
                successes += change(copyOfCoinsUsed, coin, amountSoFar + coin, amountToChange);
            }
        }

        //pass back the current
        return successes;

    } 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜