当前位置: 首页 > 知识库问答 >
问题:

如何解决金额为双精度而不是整数的硬币兑换问题

洪伟兆
2023-03-14

我如何着手解决一个类似的问题,在这个问题中,金额可以是一个双倍值(例如19.12),而不是严格意义上的int(例如19),并且测试用例将包括美元钞票和硬币?

在典型的leetcode问题中,我将创建一个dp数组,该数组将存储最少的硬币,以构成当前使用的数量。使用自底向上的处理,我将从最小的子问题(dp[0]=0)开始,然后解决手头的问题,如下所示:

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount + 1];
        Arrays.fill(dp, amount + 1);
        dp[0] = 0;
        for(int i = 0; i <= amount; i++) {
            for(int j = 0; j < coins.length; j++) {
                if(coins[j] <= i) {
                    dp[i] = Math.min(dp[i], 1 + dp[i - coins[j]]);
                }
            }
        }
        return dp[amount] > amount ? - 1 : dp[amount];
    }
}

编辑

乔尼的回答成功了。这是我的最终解决方案。基本上,最初的解决方案只能读取int金额(整美元金额0美分),但是现在,下面的程序将金额分离为钞票和硬币,并将两者转换为int值。然后,不管最初的解决方案是做什么的,新的解决方案只是分别对钞票和硬币做同样的事情。不确定这是否有意义,但解决办法是:

import java.util.Arrays;
import java.util.Scanner;

class Main {
    public static void main (String[] args) {
        int[] billDeno = new int[] {500,200,100,50,20,10,5,2,1};
        int[] coinDeno = new int[] {50,25,10,5,2,1};
        Scanner input = new Scanner(System.in);
        System.out.printf("Enter amount: ");
        double amount = input.nextDouble();
        int y = coinChange(billDeno, coinDeno, amount);
        System.out.println(y);
    }
    
    public static int coinChange(int[] billDeno, int[] coinDeno, double amount) {        
        int numDollars = (int) amount;
        int numCents = (int) ((amount - numDollars) * 100 + 0.5f);
        
        int[] dpDollars = new int[numDollars + 1];
        int[] dpCents = new int[numCents + 1];
        
        Arrays.fill(dpDollars, numDollars + 1);
        Arrays.fill(dpCents, numCents + 1);
        
        dpDollars[0] = 0;
        dpCents[0] = 0;
        
        for(int i = 0; i <= numDollars; i++) {
            for(int j = 0; j < billDeno.length; j++) {
                if(billDeno[j] <= i) {
                    dpDollars[i] = Math.min(dpDollars[i], 1 + dpDollars[i - billDeno[j]]);
                }
            }
        }
        for(int i = 0; i <= numCents; i++) {
            for(int k = 0; k < coinDeno.length; k++) {
                if(coinDeno[k] <= i) {
                    dpCents[i] = Math.min(dpCents[i], 1 + dpCents[i - coinDeno[k]]);
                }
            }
        }
        return dpDollars[numDollars] + dpCents[numCents] > amount ? -1 : dpDollars[numDollars] + dpCents[numCents];
    }
}

这可能看起来像一个hacky解决方案(尤其是接近尾声),所以请随时发布更优化的解决方案。感谢所有的帮助!


共有2个答案

鲁宏爽
2023-03-14

现在这里有一个很好的答案。

我想如果你把int改成double,它可能会工作,也可能不会。但是,它不会通过LeetCode,因为这不是所需的输入/输出:

class Solution {
    public double coinChange(double[] coins, double target) {
        if (target < 1)
            return 0;
        return helper(coins, target, new double[target]);
    }

    private double helper(double[] coins, double rem, int[] count) {
        if (rem < 0)
            return -1;
        if (rem == 0)
            return 0;
        if (count[rem - 1] != 0)
            return count[rem - 1];
        int min = Integer.MAX_VALUE;
        for (double coin : coins) {
            double res = helper(coins, rem - coin, count);
            if (res >= 0 && res < min)
                min = 1 + res;
        }

        count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
        return count[rem - 1];

    }
}

您的输入/输出可能如下所示:

coins = [1.0, 2.0, 5.0, 0.01, 0.1, 0.25, 0.5], amount = 19.12

您可能需要调试它,可能有一些typebug。

对于int,这将通过LeetCode:

class Solution {
    public int coinChange(int[] coins, int target) {
        if (target < 1)
            return 0;
        return helper(coins, target, new int[target]);
    }

    private int helper(int[] coins, int rem, int[] count) {
        if (rem < 0)
            return -1;
        if (rem == 0)
            return 0;
        if (count[rem - 1] != 0)
            return count[rem - 1];
        int min = Integer.MAX_VALUE;
        for (int coin : coins) {
            int res = helper(coins, rem - coin, count);
            if (res >= 0 && res < min)
                min = 1 + res;
        }

        count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
        return count[rem - 1];

    }
}
  • 有关更多详细信息,请参见讨论板。这里有许多公认的解决方案,包括各种语言和解释、高效算法以及渐近时间/空间复杂性分析1,2
袁恩
2023-03-14

这不适用于double

许多十进制分数(如0.10)不能精确表示为二进制浮点数。当您在Java程序中编写0.100.30时,您可以得到最佳近似值,但不能得到精确值。看,浮点数学被打破了吗?

例如,0.30不是0.10的三倍。这个程序不会找到一种方法来改变0.3。

如果你将金额和硬币价值乘以100,以美分为单位,并使用int或long。同样有效的方法是使用BigDecimal类而不是double,但是您必须使用方法调用而不是算术运算符。

 类似资料:
  • 以人民币的硬币为例,假设硬币数量足够多。要求将一定数额的钱兑换成硬币。要求兑换硬币数量最少。 思路说明: 这是用贪婪算法的典型应用。在本例中用python来实现,主要思想是将货币金额除以某硬币单位,然后去整数,即为该硬币的个数;余数则做为向下循环计算的货币金额。 这个算法的问题在于,得出来的结果不一定是最有结果。比如,硬币单位是[1,4,6],如果将8兑换成硬币,按照硬币数量最少原则,应该兑换成为

  • 我在理解动态规划中的硬币兑换问题时遇到了一个小问题。简单地说,我必须用最少数量的硬币来兑换一笔钱。 我有n种面值为1=v1的硬币

  • 我有一个练习: 您将获得不同面额的硬币和总金额。请编写一个函数来计算您需要的最少数量的硬币,以弥补该金额。如果硬币的任何组合都无法弥补该金额,请返回-1 例1: 我还谷歌了一个这样的解决方案: 我知道它是关于DP的,但是,我对它很困惑,比如,的含义是什么,为什么要添加,为什么要添加,为什么要添加1? 有人能用简单的英语指出出路吗?

  • 这是hackerrank(https://www.hackerrank.com/challenges/coin-change)的硬币更换问题。它要求计算使用给定面值的硬币对N进行更改的方法总数。 例如,有四种方法可以使用面额为1、2和3的硬币兑换4。它们是-

  • 给定一个值N,如果我们想换N美分,并且我们有无限量的S={S1,S2,…,Sm}值的硬币,我们可以用多少种方式来换?硬币的顺序无关紧要。 例如,对于N=4和S={1,2,3},有四种解:{1,1,1,1},{1,1,2},{2,2},{1,3}。所以输出应该是4。对于N=10和S={2,5,3,6},有五个解:{2,2,2,2},{2,2,3,3},{2,2,6},{2,3,5}和{5,5}。所以

  • 问题内容: 我该如何克服Java android中双精度乘法的精度问题?请注意,我正在将字符串值转换为double值。 例如:当我将两个double值相乘时: 我得到以下结果:0.8999999999999999 我得到的一些结果是。 0.6 * 3 = 1.7999999999999998; 0.2 * 0.2 = 0.04000000000000001; 等等 除了上述结果外,我想得到以下结果