没问题,我来用更简单的方式解释一下。
问题回顾
你需要计算凑成一个目标金额所需的最少硬币数量。假设我们有硬币面额数组 coins = [1, 2, 5]
和目标金额 amount = 11
。
解决方案
我们使用动态规划来解决这个问题。虽然实现中通常使用一维数组,但理解时可以将其看作一个逐步构建的二维数组。这里我们会把一维数组的思想转化为二维数组的方式来帮助理解。
动态规划表
-
定义二维数组:
- 假设有一个二维数组
dp
,dp[i][j]
表示凑成金额i
时,使用前j
种硬币的最小硬币数。 - 这个数组的行表示金额,从 0 到
amount
。 - 列表示硬币的种类(在这个例子中是 1, 2, 和 5)。
- 假设有一个二维数组
-
初始化:
dp[0][j] = 0
,因为凑成金额 0 不需要任何硬币。- 对于其他金额,初始化为一个很大的数(表示最初无法用硬币凑成该金额)。
-
填充表格:
- 对于每个金额
i
,尝试使用每种硬币coin
来更新dp[i][j]
。 - 公式为:
dp[i][j] = min(dp[i][j], dp[i - coin][j] + 1)
。
- 对于每个金额
举例
假设硬币面额为 1, 2, 5
,目标金额为 11
。我们逐步填充一个二维数组:
初始化二维数组
- 行是金额从 0 到 11。
- 列是硬币种类:1、2、5。
金额/硬币 | 1 | 2 | 5
---------|---|---|---
0 | 0 | 0 | 0
1 | 1 | ∞ | ∞
2 | 2 | 1 | ∞
3 | 3 | 2 | ∞
4 | 4 | 3 | ∞
5 | 5 | 4 | 1
6 | 6 | 5 | 2
7 | 7 | 6 | 3
8 | 8 | 7 | 4
9 | 9 | 8 | 5
10 | 10| 9 | 6
11 | 11| 10| 7
填充过程
-
金额为 1:
- 使用硬币 1 时,
dp[1][0] = dp[0][0] + 1 = 1
(用一个 1 元硬币)
- 使用硬币 1 时,
-
金额为 2:
- 使用硬币 1 时,
dp[2][0] = dp[1][0] + 1 = 2
- 使用硬币 2 时,
dp[2][1] = dp[0][1] + 1 = 1
(用一个 2 元硬币,比较取最小值)
- 使用硬币 1 时,
-
金额为 5:
- 使用硬币 1 时,
dp[5][0] = dp[4][0] + 1 = 5
- 使用硬币 2 时,
dp[5][1] = dp[3][1] + 1 = 4
- 使用硬币 5 时,
dp[5][2] = dp[0][2] + 1 = 1
(用一个 5 元硬币,最少)
- 使用硬币 1 时,
-
继续填充,直到金额 11。
最终结果
dp[11]
表示凑成金额 11 时,最少需要的硬币数。- 从表中最后一行,可以看到使用硬币
5
最少。
简化
实际实现中,我们用一维数组 dp
代替二维数组,节省空间:
dp[i]
表示凑成金额i
的最少硬币数。- 从金额
0
开始逐步计算到amount
。
希望这个简化的例子能帮助你理解!如果还有疑问,随时告诉我。