leetcode 322. 零钱兑换

leetcode 322. 零钱兑换

分析: 题意要求计算从给定的不同面额的硬币数组中能凑成总金额所需要的最少硬币个数,如果没有任何一种硬币能组成总金额,则返回-1,并且硬币的数量是无限的,因此本题可以看成是一个完全背包问题。

  • 背包容量:总金额amount
  • 物品:硬币coins

解题步骤(参考代码随想录中的动规五部曲):

  1. 确定递推数组dp的含义:将dp[i]定义为组成金额为i最少需要的硬币数量;
  2. 确定递推公式:dp[i] 可以由dp[i - coins[j]] + 1来得到,既凑成i - coins[j]的最少硬币数量为dp[i - coins[j]],那么再加上一个coins[j]就能得到凑成金额为i的硬币数量dp[i] ,由于题意是求最少硬币数量,所以递推公式为dp[i] = min(dp[i], dp[i - coins[j]] + 1);
  3. dp数组进行初始化:因为要取最小值,所以初始化不能是一个很小的值,在这里可以将dp数组全部初始化为INT_MAX(int型的最大值),其中dp[0] = 0;
  4. 确定背包和物品的遍历顺序:在这里先遍历背包和先遍历物品都一样,但是由于在这里我们将dp数组全部初始化为INT_MAX,因此在进行递归计算之前需要先判断一下i - coins[j]是否为INT_MAX,如果不是再进行计算,不然dp[i - coins[j]] + 1会溢出报错;

完整代码:

这是先遍历的物品再遍历的背包

    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 0; i < coins.size(); ++i) {
            for (int j = coins[i]; j <= amount; ++j) {
                if (dp[j - coins[i]] != INT_MAX) {
                    dp[j] = min(dp[j], dp[j - coins[i]] + 1);
                }
            }
        }

        return dp[amount] == INT_MAX ?  -1 : dp[amount];
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值