简体   繁体   中英

Recursion gives correct answer for minimum Coin Change but dynamic programming gives wrong answer

I am trying to do this problem for quite a few hours but I can't think intuitively about it. Having sort of a mental block regarding it. After many tries I was able to get recursion solution correct for cases where solution exist. So I have following questions:

  1. Recursion program is giving correct solution for input in which solution exist. How to return 'No solution exist' where solution doesn't exist. Ex for Coins [3,10], no solution exist for change 17.

  2. What is the mistake in DP program? I tried using memoization technique where I created a dictionary and added values to it but the program is not working correctly.

import math
def findMinCoins(denomination, change):
    #recursive solution
    minCoins = change
    if(len(denomination )== 0 or change ==0): #when there are no coins or change is 0
        return 0
    elif(change in denomination):
        return 1
    elif(change < min(denomination)):
        return float("inf")
    else:
        for i in denomination:
            if(i<=change):
                numCoins = 1 + findMinCoins(denomination, change - i)
                if(numCoins < minCoins):
                    minCoins = numCoins
    return minCoins

c = [3,10]
d = 30

print findMinCoins(c,d)

Now here is DP solution.

import math
coinsDict = {}

def findMinCoins(denomination, change):
    minCoins = change
    if(len(denomination )== 0 or change ==0):
        return 0
    elif(change in denomination):
        return 1
    elif(change < min(denomination)):
        return float("inf")
    else:
        for i in denomination:
            if (coinsDict.get(change)):
                print 'dictionaty',change, coinsDict.get(change)
                return coinsDict[change]
            elif(i<=change):
                numCoins = 1 + findMinCoins(denomination, change - i)
                if(numCoins < minCoins):
                    minCoins = numCoins
                    print change, numCoins
                    coinsDict[change] = numCoins

    return minCoins

c = [3,10]
d = 30

print findMinCoins(c,d)

The problem is in the way you use the memos. If you've found a solution for a particular amount of change, you never consider that there might be a better solution. Look at the logic

    if (coinsDict.get(change)):
        print 'dictionaty',change, coinsDict.get(change)
        return coinsDict[change]
    elif(i<=change):
        numCoins = 1 + findMinCoins(denomination, change - i)

On your first pass through the recursion, you walk all the way down and find that you can handle 30 cents with 10 coins of 3. Then you unwind back to the top of the stack and try again with a 10-cent piece ... but before you bother to look for a solution the above logic says, "I already know how to handle 30 cents: return 10 coins." It never gets to explore solutions involving other amounts.

If you reverse the order of checking your denominations, you'll get the desired solution. Make sure you try other test cases: you should find that this simple repair isn't enough to fix your logic. For instance, try

c = [3, 11, 13] d = 22

If you fail to look for better solutions, you'll find the 4-coin solution of 13, 3, 3, 3 and miss the 11, 11 answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM