The minimum number of coins the sum of which is S

后端 未结 12 1349
我寻月下人不归
我寻月下人不归 2020-11-30 05:06

Given a list of N coins, their values (V1, V2, ... , VN), and the total sum S. Find the minimum number of coins the sum of which is S (we can use as many coins of one type a

相关标签:
12条回答
  • 2020-11-30 05:45

    The main idea is - for each coin j, value[j] <= i (i.e sum) we look at the minimum number of coins found for i-value[j] (let say m) sum (previously found). If m+1 is less than the minimum number of coins already found for current sum i then we update the number of coins in the array.

    For ex - sum = 11 n=3 and value[] = {1,3,5}
    Following is the output we get

    i- 1  mins[i] - 1  
    i- 2  mins[i] - 2  
    i- 3  mins[i] - 3  
    i- 3  mins[i] - 1  
    i- 4  mins[i] - 2  
    i- 5  mins[i] - 3  
    i- 5  mins[i] - 1  
    i- 6  mins[i] - 2  
    i- 7  mins[i] - 3  
    i- 8  mins[i] - 4  
    i- 8  mins[i] - 2  
    i- 9  mins[i] - 3  
    i- 10 mins[i] - 4  
    i- 10 mins[i] - 2  
    i- 11 mins[i] - 3 
    

    As we can observe for sum i = 3, 5, 8 and 10 we improve upon from our previous minimum in following ways -

    sum = 3, 3 (1+1+1) coins of 1 to one 3 value coin  
    sum = 5, 3 (3+1+1) coins to one 5 value coin  
    sum = 8, 4 (5+1+1+1) coins to 2 (5+3) coins  
    sum = 10, 4 (5+3+1+1) coins to 2 (5+5) coins.  
    

    So for sum=11 we will get answer as 3(5+5+1).

    Here is the code in C. Its similar to pseudocode given in topcoder page whose reference is provided in one of the answers above.

    int findDPMinCoins(int value[], int num, int sum)
    {
        int mins[sum+1];
        int i,j;
    
       for(i=1;i<=sum;i++)
           mins[i] = INT_MAX;
    
        mins[0] = 0;
        for(i=1;i<=sum;i++)
        {
            for(j=0;j<num;j++)
            {
                if(value[j]<=i && ((mins[i-value[j]]+1) < mins[i]))
                {
                    mins[i] = mins[i-value[j]] + 1; 
                    printf("i- %d  mins[i] - %d\n",i,mins[i]);
                }
            }
        }
        return mins[sum];
    }
    
    0 讨论(0)
  • 2020-11-30 05:46

    Question is already answered but I wanted to provide working C code that I wrote, if it helps anyone. enter code here

    Code has hard coded input, but it is just to keep it simple. Final solution is the array min containing the number of coins needed for each sum.

    #include"stdio.h"
    #include<string.h>
    
    int min[12] = {100};
    int coin[3] = {1, 3, 5};
    
    void
    findMin (int sum) 
    {
        int i = 0; int j=0;
        min [0] = 0; 
    
        for (i = 1; i <= sum; i++) {
            /* Find solution for Sum = 0..Sum = Sum -1, Sum, i represents sum
             * at each stage */
            for (j=0; j<= 2; j++) {
                /* Go over each coin that is lesser than the sum at this stage
                 * i.e. sum = i */
                if (coin[j] <= i) {
                    if ((1 + min[(i - coin[j])]) <= min[i]) { 
                        /* E.g. if coin has value 2, then for sum i = 5, we are 
                         * looking at min[3] */
                        min[i] = 1 + min[(i-coin[j])]; 
                        printf("\nsetting min[%d] %d",i, min[i]);
                    }
                }
            }
        }
    }
    void
    initializeMin()
    {
        int i =0;
        for (i=0; i< 12; i++) {
            min[i] = 100;
        }
    }
    void
    dumpMin() 
    {
        int i =0;
        for (i=0; i< 12; i++) {
            printf("\n Min[%d]: %d", i, min[i]);
        }
    }
    int main() 
    {
        initializeMin();
        findMin(11);
        dumpMin(); 
    }
    
    0 讨论(0)
  • 2020-11-30 05:46

    I knew this is a old question, but this is a solution in Java.

    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    
    public class MinCoinChange {
    
        public static void min(int[] coins, int money) {
            int[] dp = new int[money + 1];
            int[] parents = new int[money + 1];
            int[] usedCoin = new int[money + 1];
            Arrays.sort(coins);
            Arrays.fill(dp, Integer.MAX_VALUE);
            Arrays.fill(parents, -1);
    
            dp[0] = 0;
            for (int i = 1; i <= money; ++i) {
                for (int j = 0; j < coins.length && i >= coins[j]; ++j) {
                    if (dp[i - coins[j]] + 1 < dp[i]) {
                        dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                        parents[i] = i - coins[j];
                        usedCoin[i] = coins[j];
                    }
                }
            }
            int parent = money;
            Map<Integer, Integer> result = new HashMap<>();
            while (parent != 0) {
                result.put(usedCoin[parent], result.getOrDefault(usedCoin[parent], 0) + 1);
                parent = parents[parent];
            }
            System.out.println(result);
        }
    
        public static void main(String[] args) {
            int[] coins = { 1, 5, 10, 25 };
            min(coins, 30);
        }
    }
    
    0 讨论(0)
  • 2020-11-30 05:48
    def leastCoins(lst, x):
    temp = []
    if x == 0:
        return 0
    else:       
        while x != 0:
            if len(lst) == 0:
                return "Not Possible"
            if x % max(lst) == 0:
                temp.append((max(lst), x//max(lst)))
                x = 0
            elif max(lst) < x:
                temp.append((max(lst), x//max(lst)))
                x = x % max(lst)
                lst.remove(max(lst))
            else:
                lst.remove(max(lst))
    return dict(temp) 
    

    leastCoins([17,18,2], 100652895656565)

    0 讨论(0)
  • 2020-11-30 05:49

    Lots of people already answered the question. Here is a code that uses DP

    public static List<Integer> getCoinSet(int S, int[] coins) {
        List<Integer> coinsSet = new LinkedList<Integer>();
        if (S <= 0) return coinsSet;
    
        int[] coinSumArr = buildCoinstArr(S, coins);
    
        if (coinSumArr[S] < 0) throw new RuntimeException("Not possible to get given sum: " + S);
    
        int i = S;
        while (i > 0) {
            int coin = coins[coinSumArr[i]];
            coinsSet.add(coin);
            i -= coin;
        }
    
        return coinsSet;
    }
    
    public static int[] buildCoinstArr(int S, int[] coins) {
        Arrays.sort(coins);
        int[] result = new int[S + 1];
    
        for (int s = 1; s <= S; s++) {
            result[s] = -1;
            for (int i = coins.length - 1; i >= 0; i--) {
                int coin = coins[i];
                if (coin <= s && result[s - coin] >= 0) {
                    result[s] = i;
                    break;
                }
            }
        }
    
        return result;
    }
    
    0 讨论(0)
  • 2020-11-30 05:52

    The precise answer to this problem is well explained here. http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg

    0 讨论(0)
提交回复
热议问题