题目链接:518. Coin Change 2
我的源码:源码
最近看到这道题,但是看网大部分教程感觉思路都写的不是特别的详细。分享一下个人的解题思路。
题目:
给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
示例 1:
1 | 输入: amount = 5, coins = [1, 2, 5] |
一开始,我想到的是用动态规划的思路去解决这道题,假设dp[n] 为凑成 n 的组合数,最后发现思维上无法找到动态方程。参考了,别人的解决方案发现需要用两个变量来解决这个问题。
思路
设dp[i][j] 为用前 i 种硬币达到总金额 j 的硬币组合数。对于dp[i][j],我们可能会出现两种情况达到效果,第一种是我们没有使用第i种硬币达到j元的组合数,第二种是使用了第i种硬币达到j的组合数。
- 没用使用第i种硬币的组合数: dp[i - 1][j]
- 使用了第i种硬币的组合数:dp[i][j - conin[i]], j >= conin[i]
得到动态方程: dp[i][j] = dp[i-1][j] + j >= coin[i] ? dp[i][j - coin[i]] : 0
优化
其实我们并不需要记录所有的状态,我们只需要记录每增加一枚硬币带来的改变。
以 amount = 5,coins = [1,2,5] 为例。我们可以用 dp[n] 记录当前使用硬币对应钱组合数。显然dp[0] = 1是一直成立的。
当我们什么硬币都不使用的时候
n | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
dp[n] | 1 | 0 | 0 | 0 | 0 | 0 |
使用硬币 1,只用 n >= 1 会受到影响
n | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
dp[n] | 1 | 1 |
1 |
1 |
1 |
1 |
加上使用硬币 2,只用 n >= 2 会受到影响
n | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
dp[n] | 1 | 1 | 2 |
2 |
3 |
3 |
加上使用硬币 5,只用 n >= 5 会受到影响
n | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
dp[n] | 1 | 1 | 2 | 2 | 3 | 4 |
如何求dp[n]
假设我们要求加上使用第j种币时的dp[n], 当前的dp[n]可以看做是不使用第j种币得到 n 的组合数。根据前面的公式我们可以知道,我们只需要加上使用第j种币时的组合数即可,即加上dp[n - coin[j]];代码也非常精炼。
1 |
|