力扣-518-零钱兑换II

题目:
518.518. Coin Change 2(medium)


解题思路:


代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
java:
原始思想:
public int change(int amount, int[] coins) {
int n = coins.length;

//类比背包问题的dp[i][v]含义:表示前i个物品恰好放入容量为v的背包时获取到的最大价值
//这里dp[i][j]含义为:前i个硬币恰好组成j金额时组合总数
int[][] dp = new int[n+1][amount+1];

//base case
dp[0][0] = 1;

for(int i = 1;i<=n;i++){
for(int j = 0;j<=amount;++j){
for(int k = 0;k*coins[i-1] <= j;k++){////每次都把前一种硬币全部扫一遍
dp[i][j] += dp[i-1][j-k*coins[i-1]];
}
}
}
return dp[n][amount];
}

优化过后:
public int change(int amount, int[] coins) {
int n = coins.length;

//类比背包问题的dp[i][v]含义:表示前i个物品恰好放入容量为v的背包时获取到的最大价值
//这里dp[i][j]含义为:前i个硬币恰好组成j金额时组合总数
int[][] dp = new int[n+1][amount+1];

//base case
for(int i = 0;i<=n;i++) dp[i][0] = 1;//金额为0,只有不选任何这一种
for(int j = 1;j<=amount;j++) dp[0][j] = 0;

for(int i = 1;i<=n;i++){
for(int j = 1;j<=amount;++j){
dp[i][j] = dp[i-1][j];
if(j - coins[i-1] >= 0)//判断能不能选coins[i-1]
dp[i][j] += dp[i][j - coins[i-1]];//每个物品可以选无限次,所以由之前的dp数组补上
System.out.print(dp[i][j] + ",");
}
System.out.println();
}
return dp[n][amount];
}

再优化:
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] + dp[j - coins[i]];
}
}
// for(int i = 0;i<=amount;i++){
// System.out.print(dp[i] + ",");
// }
return dp[amount];
}

//https://leetcode-cn.com/problems/coin-change-2/solution/bei-bao-si-xiang-jie-jue-ling-qian-dui-huan-wen-ti/