518.零钱兑换 II

【LetMeFly】518.零钱兑换 II

力扣题目链接:https://leetcode.cn/problems/coin-change-2/

给你一个整数数组 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

方法一:动态规划

用$dp[i]$表示硬币总金额为$i$的方案数

初始值$dp[0] = 1$(硬币总和为0的方案只有一种:0枚硬币)

转移方程$dp[i] = \sum dp[i - coin_j]$

注意,$[1, 2]$和$[2, 1]$是一种方案。因此为了避免硬币顺序不同导致方案数重复计算的情况,我们应该按照硬币顺序进行模拟。即:先全用$1$元硬币,再尝试用$2$元硬币替换数个$1$元硬币,再考虑$3$元(如果有的话)…

  • 时间复杂度$O(len(coins) \times amount)$
  • 空间复杂度$O(amount)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1, 0);
dp[0] = 1;
for (int& t : coins) {
for (int i = t; i <= amount; i++)
dp[i] += dp[i - t];
}
return dp.back();
}
};

Pythonn

1
2
3
4
5
6
7
8
9
10
from typing import List

class Solution:
def change(self, amount: int, coins: List[int]) -> int:
dp = [0] * (amount + 1)
dp[0] = 1
for coin in coins:
for i in range(coin, amount + 1):
dp[i] += dp[i - coin]
return dp[-1]

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/127936876


518.零钱兑换 II
https://blog.letmefly.xyz/2022/11/19/LeetCode 0518.零钱兑换II/
作者
Tisfy
发布于
2022年11月19日
许可协议