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

最小硬币变化自上而下DP与1D阵列

秦斌
2023-03-14

这是Leetcode的硬币兑换问题,在这里,给定面额的硬币是无限的,你必须找到满足给定金额所需的最小硬币。我尝试使用自顶向下的1D缓存阵列解决这个问题。基本测试用例通过了,但对于一些较大的总和和面额值,它失败了。我的假设是,我在遍历数组时做错了什么,可能遗漏了一些子问题的计算,但无法找到解决问题的方法。

问题陈述:

You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.

Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
You may assume that you have an infinite number of each kind of coin.

Input: coins = [1,2,5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1

我的解决方案:


/* Test case, it's failing for: 
Input: coins: [186,419,83,408] 
sum = 6249 
Output: 26 
Expected: 20 
*/
------------------------------------------------------------------------

    int fncUtil(int dp[], int a[], int sum, int n, int curCoins) {


        if(sum == 0) {
            return curCoins;
        }

        if(n < 0 || sum < 1) {
            return Integer.MAX_VALUE;
        }

        if(dp[sum] != Integer.MAX_VALUE) {
            return dp[sum];
        }

        dp[sum] = Math.min(fncUtil(dp, a, sum - a[n], n, curCoins+1),
                    fncUtil(dp, a, sum, n-1, curCoins));

        return dp[sum];

    }
    public int coinChange(int[] a, int sum) {
        Arrays.sort(a);
        int n = a.length;
        // minCoins = Integer.MAX_VALUE;
        int dp[] = new int[sum+1];
        for(int i = 0; i <= sum; i++) {
            dp[i] = Integer.MAX_VALUE;
        }
        dp[0] = 0;
        int minCoins = fncUtil(dp, a, sum, n-1, 0);
        if(minCoins == Integer.MAX_VALUE) return -1;
        return minCoins;
    }

共有1个答案

万俟浩
2023-03-14

似乎在存在值的情况下不更新dp数组

if(dp[sum] != Integer.MAX_VALUE) {
         return dp[sum];
  }

也许您需要从三个变体中选择最好的

  dp[sum] = Math.min(dp[sum], 
         Math.min(fncUtil(dp, a, sum - a[n], n, curCoins+1), fncUtil(dp, a, sum, n-1, curCoins)));

但是我们可以使用自下而上的顺序(未检查)来解决这个问题,而无需递归

public int coinChange(int[] a, int sum) {
    int n = a.length;
    int dp[] = new int[sum+1];
    for(int i = 0; i <= sum; i++) {
        dp[i] = Integer.MAX_VALUE - 1;
    }
    dp[0] = 0;
    for(int i = 0; i < n; i++) {
        for (int k = a[i]; k <= sum; k++) {
               dp[k] = Math.min(dp[k], dp[k-a[i]] + 1);
        } 
    }
    return dp[sum];
}
 类似资料:
  • 下面是最小硬币变化问题的蛮力解决方案。它需要一个int更改,也就是需要进行的更改,以及一系列硬币面值。它返回进行更改所需的最低硬币。 我如何修改它以同时返回一组硬币? 例如,如果要求给出值为[1,2,5]的10美分的零钱,它应该返回2个硬币分钟和一个数组[0,0,2]的2个硬币。

  • 我正在构建一种自下而上的方法来解决硬币兑换问题。我必须提供所需的最低硬币数量,以提供所需的零钱。可能由于给定的面额无法形成值,因此无法给出更改。 例如,如果给定的面额是{4,8},他们要求改变5,那么就不可能给5。我构建了下面的程序,它适用于大多数情况,除非不可能形成所请求的更改。例如,当面值仅为{4}而我请求5时,它返回一个假值。我能做些什么来纠正这个问题? 这里P表示请求的更改,S是存储在数组

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

  • 给定一组硬币面额和一个,找出所有可能的组合,使硬币总数达到最小。在我的解决方案中,我在中记录了总计为的最小硬币数。我不确定这将如何修改以存储总计为的实际硬币,并确保在这种情况下包括这两种可能性。我看过其他关于堆栈溢出的代码,但我只找到可以打印任何一个最佳解决方案的代码。 输入:最小硬币(10,[2,3,5,6,7,8]) 输出:[[5,5],[2,8]]

  • 下面是最小硬币兑换问题的强力解决方案。它需要一个整数A(这是需要进行的更改)和一组硬币面额。它返回一个对象results,该对象具有基于硬币面额数组和硬币数组可以返回的最小硬币数。 例如,如果要求以的值为美分提供零钱,则它应返回分钟硬币和两个一角硬币的数组。 它返回正确的最小值,但不是正确的硬币数组。

  • 硬币兑换是一个非常普遍的问题,它问你有多少种方法可以使用硬币(C[0],C[1]…C[K-1])得到N美分的总和。DP解决方案是使用方法s(N,K)=s(N,K-1)s(N-C[K-1],K),其中s(N,K)是与前K个硬币(按升序排序)求和N的方法数量。这意味着使用前K个硬币获得N美分的方式数量是不使用第K个硬币获得相同金额的方式数量加上获得N-第K个硬币的方式数量的总和。我真的不明白你怎么会想