LeetCode 322 零钱兑换

题目描述

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1

你可以认为每种硬币的数量是无限的。

思路

这是一个完全背包问题,背包问题当满足:物品不限制放入背包的个数,就是完全背包问题。背包问题一般要注意两个顺序:

  1. 循环嵌套的顺序,是把遍历物品的循环放外层还是把遍历背包的循环放在外层。
  2. 遍历dp数组的先后顺序,是从前往后遍历还是从后往前遍历。

这道题使用一维dp,注意在遍历dp数组的时候要从前往后,因为一个物品可以放多次。

具体步骤

1 确定dp数组的意义

dp[j]表示当总金额为j时,最少用dp[j]枚硬币可以凑出来

2 确定状态转移方程

dp[j] = min{dp[j - coin] + 1} (coin <= j,且coin属于coins数组)

3 初始状态

由于这题是求最小值,所以初始值设置为正无穷,又根据状态转移方程可知,dp数组中下标较大的值是由下标较小的值+1得到,所以dp[0]初始值应该设置为0。

代码

class Solution {
    public int coinChange(int[] coins, int amount) {
        if (amount == 0) return 0;
        int[] dp = new int[amount + 1];
        //dp[j]表示要将总金额凑成amount所需要的最少硬币数
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int i = 0; i < coins.length; i++) {
            for (int j = coins[i]; j <= amount; j++) {
                if (dp[j - coins[i]] != Integer.MAX_VALUE) {
                    dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
                }
            } 
        }
        return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
    }
}
posted @ 2024-08-01 14:05  wutao666  阅读(59)  评论(0)    收藏  举报