夯实算法-零钱兑换 II

126 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情

题目:LeetCode

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

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。 

题目数据保证结果符合 32 位带符号整数。

示例 1:

输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

示例 2:

输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额 2 的硬币不能凑成总金额 3 。

示例 3:

输入: amount = 10, coins = [10] 
输出: 1

提示:

  • 1 <= coins.length <= 300
  • 1 <= coins[i] <= 5000
  • coins 中的所有值 互不相同
  • 0 <= amount <= 5000

解题思路

根据题意分析这是一个动态规划题型。

  • 1.dp[n]表示容量为n的组合总数
  • 2.dp[j] += dp[j - coins[i]],凡是计算组合总数的都是累加所有情况的
  • 3.遍历方式,与之前的01背包不同,这里只能是外层遍历背包种类,内层遍历容量,因为考虑到组合总数和排列总数的区别,题目要求的是组合总数,那么就必须外层遍历种类,内层遍历种类
  • 4.初始化必须初始dp[0] = 1,因为所有遍历累加都是基于这个的,因此必须初始化dp[0],其他的默认为0

代码实现

public int change(int amount, int[] coins) {
    int n = coins.length;
    int[] dp = new int[amount + 1];
    dp[0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = coins[i]; j <= amount; j++) {
            dp[j] += dp[j - coins[i]];
        }
    }
    return dp[amount];
}

运行结果

Snipaste_2023-02-11_21-14-25.png

复杂度分析

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)  一起分享知识, Keep Learning!