比力扣所有题解都易懂 leetcode 力扣 322 零钱兑换

95 阅读1分钟

完全背包问题

1amount,每个数把每个硬币减个遍,取他们中的最小值。

一开始我犯了个低级错误,把硬币小到大排序,然后从后往前遍历,相减大于等于零就停下。这样是错的,amount小还好,如果amount很大的话,结果可能是错的。所以要遍历所有硬币,取最小值。

1.jpeg

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 = 1; i <= amount; i++) {
            for (int coin : coins) {

                if (i - coin >= 0) {
                    dp[i] = Math.min(dp[i], dp[i - coin] + 1);
                }
            }
        }

        return dp[amount] > amount ? -1 : dp[amount];
    }
}

其实这道题最难的点是,coins = [2], amount = 3,或者coins = [2], amount = 1,要返回-1,怎么办?

  1. 如果硬币凑不整amount,必定有某个dp[i]是未修改过的。比如上面例子的dp[1],均为初始值。
  2. 如果硬币都是一块钱,那么肯定有dp[amount] == amount

所以我们可以用amount + 1初始化dp数组(而不是amount,上述第二点),如果有某个dp[i]未修改过,最终dp[amount] > amount