【问题标题】:Coin Combinations Through Brute Force通过蛮力进行硬币组合
【发布时间】:2015-02-26 20:34:33
【问题描述】:

我有一些代码可以蛮力解决以下问题:

给定一组 x 个硬币和要达到的目标总和,达到该目标所需的最少硬币数量是多少?

到目前为止的代码:

import java.util.ArrayList;
import java.util.Arrays;

public class coinsSum {
    public static int min = Integer.MAX_VALUE;
    public static int[] combination;
    public static final int TARGET = 59;

    public static void main(String[] args) {
        long start = System.nanoTime();

        int[] validCoins = new int[] {1, 2, 5, 10, 20};
        Arrays.sort(validCoins);
        int len = validCoins.length;

        ArrayList<Integer> maxList = new ArrayList<Integer>();
        for(int c : validCoins) {
            maxList.add(TARGET / c);
        }

        int[] max = new int[len];
        for(int i = 0; i < len; i++) {
            max[i] = maxList.get(i).intValue();
        }

        permutations(new int[len], max, validCoins, 0); // bread&butter

        if(min != Integer.MAX_VALUE) {
            System.out.println();
            System.out.println("The combination " + Arrays.toString(combination) + " uses " + min + " coins to make the target of: " + TARGET);
        } else {
            System.out.println("The target was not reachable using these coins");
        }

        System.out.println("TOOK: " + (System.nanoTime() - start) / 1000000 + "ms");
    }

    public static void permutations(int[] workspace, int[] choices, int[] coins, int pos) {
        if(pos == workspace.length) {
            int sum = 0, coinCount = 0;
            System.out.println("TRYING " + Arrays.toString(workspace));
            for(int a = 0; a < coins.length; a++) {
                sum += workspace[a] * coins[a];
                coinCount += workspace[a];
            }
            if(sum == TARGET) {
                // System.out.println(Arrays.toString(n)); //valid combinations
                if(coinCount < min) {
                    min = coinCount;
                    combination = workspace;
                    System.out.println(Arrays.toString(combination)+" uses " + min + " coins");
                }
            }
            return;
        }
        for(int i = 0; i <= choices[pos]; i++) {
            workspace[pos] = i;
            permutations(workspace, choices, coins, pos + 1);
        }
    }
}

这个解决方案使用递归,有没有办法在java中使用循环进行计算组合?

如何迭代所有可能的组合?

【问题讨论】:

  • 如果代码有效并且您只是在寻求改进,请转到codereview.stackexchange.com
  • “有什么办法吗?”是的。其他问题太笼统了,提到的代码审查网站是个好主意。
  • 我确实发布了这个版本,但没有收到任何回复,所以我在这里寻求帮助 @markspace 我将编辑问题,然后使其不那么通用
  • 可以重复硬币吗
  • @Amir 是的,您可以拥有无​​限数量的任何硬币,但如果您拥有超过 T/C 的硬币,它将超过目标,其中 T 是目标,c 是硬币值,例如。 T = 5, C = 2, 其中 5/2 = 2 在有效解中是最有可能的

标签: java optimization dynamic-programming


【解决方案1】:

您可以对硬币数组进行排序。然后从右到左,不断从目标值中减去,直到目标值的剩余值更大。在硬币数组中向左移动并重复该过程。

例子:

{1, 2, 5, 10, 20}
num = 59

Try coins from right to left:
59 - 20 = 39
So far coins used [20]

39 - 20 = 19
So far coins used [20,20]

19 - 20 = -1, Can't use 20!
19 - 10 = 9
So far coins used [20,20,10]

9 - 10 = -1, Can't use 10!
9 - 5 = 4
So far coins used [20,20,10,5]

4 - 5 = -1, Can't use 5!
4 - 2 = 2
So far coins used [20,20,10,5,2]

2 - 2 = 0
So far coins used [20,20,10,5,2,2]
Total coin used 6

【讨论】:

  • 这适用于某些硬币列表(美国硬币就是一个例子),但不适用于其他列表。例如,如果您有硬币 {1, 3, 4} 并且您想要制作 6,那么该算法将产生 [4, 1, 1] 的答案,但最佳结果是 [3,3]
【解决方案2】:

这是python中的一个解决方案,它使用动态编程来找到达到目标值的最小硬币数。

算法如下

dp[i][target] = minimum number of coins required required to acheive target using first i coin
dp[i][target] = min(dp[i-1][target],dp[i-1][target-coin[i]]+1)
dp[i-1][target] denotes not using the ith coin
dp[i-1][target-coin[i]] denotes making use of ith coin

由于您正在检查每个硬币是否包含它,因此算法正在枚举所有可能的组合。

这是上述算法的空间优化版本

maxvalue = 10 ** 9
def minchange(coins, target):
    no_of_coins = len(coins)
    dp = [maxvalue for i in range(target + 1) ]
    dp[0] = 0
    for i in range(no_of_coins):
        for j in range(coins[i], target + 1):
            dp[j] = min(dp[j], dp[j - coins[i]] + 1)
    return dp[target]

【讨论】:

    【解决方案3】:

    我发现了一种动态编程方法,它绝对没有优化,但如果有人感兴趣的话,对于高达 10000 的目标数来说也不错

    import java.util.*;
    
    public class coinSumMinimalistic {
        public static final int TARGET = 12003;
        public static int[] validCoins = {1, 3, 5, 6, 7, 10, 12};
    
        public static void main(String[] args) {
            Arrays.sort(validCoins);
    
            sack();
        }
    
        public static void sack() {
            Map<Integer, Integer> coins = new TreeMap<Integer, Integer>();
            coins.put(0, 0);
            int a = 0;
            for(int i = 1; i <= TARGET; i++) {
                if(a < validCoins.length && i == validCoins[a]) {
                    coins.put(i, 1);
                    a++;
                } else coins.put(i, -1);
            }
            for(int x = 2; x <= TARGET; x++) {
                if(x % 5000 == 0) System.out.println("AT: " + x);
                ArrayList<Integer> list = new ArrayList<Integer>();
                for(int i = 0; i <= x / 2; i++) {
                    int j = x - i;
                    list.add(i);
                    list.add(j);
                }
                coins.put(x, min(list, coins));
            }
            System.out.println("It takes " + coins.get(TARGET) + " coins to reach the target of " + TARGET);
        }
    
        public static int min(ArrayList<Integer> combos, Map<Integer, Integer> coins) {
            int min = Integer.MAX_VALUE;
            int total = 0;
            for(int i = 0; i < combos.size() - 1; i += 2) {
                int x = coins.get(combos.get(i));
                int y = coins.get(combos.get(i + 1));
                if(x < 0 || y < 0) continue;
                else {
                    total = x + y;
                    if(total > 0 && total < min) {
                        min = total;
                    }
                }
            }
            int t = (min == Integer.MAX_VALUE || min < 0) ? -1:min;
            return t;
        }
    
        public static void print(Map<Integer, Integer> map) {
            for(Map.Entry<Integer, Integer> entry : map.entrySet()) {
                System.out.println("[" + entry.getKey() + ", " + entry.getValue() + "]");
            }
            System.out.println();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      相关资源
      最近更新 更多