1.零钱兑换
Leetcode 322;medium;
数组中给出面额,amount为要兑换到的钱,求兑换出的最少钱币的张数。
我们采用自下而上的方式进行思考。在计算 F(i) 之前,我们先计算出 F(0)-F(i-1) 的答案。
例如:coins = [1, 2, 5], amount = 11
F(i) | 最小硬币数量 |
---|---|
F(0) | 0 //金额为0不能由硬币组成 |
F(1) | 1 //F(1)=min(F(1-1)+F(1-2)+F(1-5))+1=1 |
F(2) | 1 //F(2)=min(F(2-1)+F(2-2)+F(2-5))+1=1 |
F(3) | 2 //F(3)=min(F(3-1)+F(3-2)+F(3-5))+1=2 |
F(4) | 2 //F(4)=min(F(4-1)+F(4-2)+F(4-5))+1=2 |
… | … |
F(11) | 3 //F(11)=min(F(11-1)+F(11-2)+F(11-5))+1=3 |
package dynamicprogram;
import java.util.Arrays;
public class Main0322零钱兑换 {
public static void main(String[] args) {
System.out.println(new Solution322().coinChange(new int[] { 1, 2, 5 }, 11));
}
}
// F(11)=min(F(11-1)+F(11-2)+F(11-5))+1
class Solution322 {
public int coinChange(int[] coins, int amount) {// [1,2,5] 11
int max = amount + 1; //max = 12
int[] dp = new int[amount + 1]; // dp长度12
Arrays.fill(dp, max); // 填充12
dp[0] = 0; // 0 无法兑换出
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
if (i >= coins[j]) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];// -1时无法兑换
}
}
2.零钱兑换Ⅱ
Leetcode 518;medium;
给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
package dynamicprogram;
import java.util.Arrays;
public class Main0518零钱兑换的方法数Ⅱ {
public static void main(String[] args) {
System.out.println(new Solution518().change(11, new int[]{1,2,5}));
}
}
class Solution518 {
public int change(int amount, int[] coins) {
int[] dp = new int[amount + 1];
dp[0] = 1;
for (int i = 0; i < coins.length; i++) {
for (int j = 0; j < dp.length; j++) {
if (j - coins[i] >= 0) {
dp[j] += dp[j - coins[i]];
}
}
// System.out.println("当有前" + (i + 1) + "张RMB:" + Arrays.toString(dp));
}
return dp[amount];
}
}