Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamic programming coin change that return an array

I am trying to get all the coins that are the sum of target amount. I was able to get the amount of coins needed. How would i go about solving it.

You can use the same coins unlimited eg. change([2], 10) => [2, 2, 2, 2, 2]

def change(coins, amount):
    result = [amount+1] * (amount+1)

    result[0] = 0

    for i in range(1, amount+1):
        for coin in coins:
            if i >= coin:
                result[i] = min(result[i], result[i-coin] + 1)

    if result[amount] == amount+1:
        return -1

    return result[amount]

change([1, 2, 5,8], 7) => [5, 2] order does not matter.

like image 897
mateo Avatar asked May 13 '26 03:05

mateo


2 Answers

If you use dyanmic programming you can only get the best result, you can achieve this by using a array to store the middle result of dynamic programming, I have modified based on your dp version:

def change(coins, amount):
    result = [amount+1] * (amount+1)
    coins_results = [[] for _ in range(amount+1)]

    result[0] = 0

    for i in range(1, amount+1):
        for coin in coins:
            if i >= coin and result[i - coin] + 1 < result[i]:
                result[i] = result[i-coin] + 1
                coins_results[i] = coins_results[i-coin] + [coin]

    if result[amount] == amount+1:
        return []

    return coins_results[amount]

test:

print(change([1, 2, 5, 8], 7))
print(change([2], 10))

output:

[5, 2]
[2, 2, 2, 2, 2]

here is a version to output all the result by backtracking:

def change(coins, amount):
    res = []

    def backtrack(end, remain, cur_result):
        if end < 0: return
        if remain == 0:
            res.append(cur_result)
            return
        if remain >= coins[end]:
            backtrack(end, remain - coins[end], cur_result + [coins[end]])
        backtrack(end - 1, remain, cur_result)

    backtrack(len(coins) - 1, amount, [])
    return res

test:

print(change([1, 2, 5, 8], 7))
print(change([2], 10))

output:

[[5, 2], [5, 1, 1], [2, 2, 2, 1], [2, 2, 1, 1, 1], [2, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1]]
[[2, 2, 2, 2, 2]]

Hope that helps you, and comment if you have further questions. : )

like image 57
recnac Avatar answered May 14 '26 15:05

recnac


If you want to obtain all combinations that correspond to the target amount you can use the following generator:

def change(coins, amount):
    for i, coin in enumerate(coins):
        if coin == amount:
            yield (coin,)
        elif coin < amount:
            yield from ((coin,) + x for x in change(coins[i:], amount - coin))

print(list(change([2], 10)))  # [(2, 2, 2, 2, 2)]
print(list(change([1, 2, 5, 8], 7)))  # [(1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 2), (1, 1, 1, 2, 2), (1, 1, 5), (1, 2, 2, 2), (2, 5)]
like image 26
a_guest Avatar answered May 14 '26 16:05

a_guest