|
|
package 第03期.mca_10;
|
|
|
|
|
|
// 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额
|
|
|
// 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0
|
|
|
// 假设每一种面额的硬币有无限个
|
|
|
// 题目数据保证结果符合 32 位带符号整数
|
|
|
// 测试链接 : https://leetcode.cn/problems/coin-change-ii/
|
|
|
public class Code01_CoinChange {
|
|
|
|
|
|
public static int change1(int aim, int[] arr) {
|
|
|
return ways(arr, 0, aim);
|
|
|
}
|
|
|
|
|
|
// arr[i....]所有的面值,每一种面值可以使用无限张
|
|
|
// 找的钱数是r,请返回方法数
|
|
|
public static int ways(int[] arr, int i, int r) {
|
|
|
if (r < 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
// r >= 0
|
|
|
if (i == arr.length) {
|
|
|
// 已经没有面值了! 0元,1种,不用任何钱
|
|
|
// >0 元,0种方法
|
|
|
return r == 0 ? 1 : 0;
|
|
|
}
|
|
|
// r >= 0 并且 还有面值
|
|
|
// 可能性1 : 就是不用当前面值了,
|
|
|
int p1 = ways(arr, i + 1, r);
|
|
|
// 可能性2 : 用1张当前的面值
|
|
|
int p2 = ways(arr, i, r - arr[i]);
|
|
|
return p1 + p2;
|
|
|
}
|
|
|
|
|
|
public static int change2(int aim, int[] arr) {
|
|
|
int n = arr.length;
|
|
|
int[][] dp = new int[n][aim + 1];
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
for (int r = 0; r <= aim; r++) {
|
|
|
dp[i][r] = -1; // -1表示所有状态没算过!
|
|
|
}
|
|
|
}
|
|
|
return ways2(arr, 0, aim, dp);
|
|
|
}
|
|
|
|
|
|
public static int ways2(int[] arr, int i, int r, int[][] dp) {
|
|
|
if (r < 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
if (i == arr.length) {
|
|
|
return r == 0 ? 1 : 0;
|
|
|
}
|
|
|
if (dp[i][r] != -1) {
|
|
|
return dp[i][r];
|
|
|
}
|
|
|
int p1 = ways2(arr, i + 1, r, dp);
|
|
|
int p2 = ways2(arr, i, r - arr[i], dp);
|
|
|
int ans = p1 + p2;
|
|
|
dp[i][r] = ans;
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
// public static int change1(int aim, int[] arr) {
|
|
|
// return process1(arr, 0, aim);
|
|
|
// }
|
|
|
//
|
|
|
// public static int process1(int[] arr, int i, int j) {
|
|
|
// if (j < 0) {
|
|
|
// return 0;
|
|
|
// }
|
|
|
// if (i == arr.length) {
|
|
|
// return j == 0 ? 1 : 0;
|
|
|
// }
|
|
|
// return process1(arr, i + 1, j) + process1(arr, i, j - arr[i]);
|
|
|
// }
|
|
|
//
|
|
|
// public static int change2(int aim, int[] arr) {
|
|
|
// int n = arr.length;
|
|
|
// int[][] dp = new int[n][aim + 1];
|
|
|
// for (int i = 0; i < n; i++) {
|
|
|
// for (int j = 0; j <= aim; j++) {
|
|
|
// dp[i][j] = -1;
|
|
|
// }
|
|
|
// }
|
|
|
// return process2(arr, 0, aim, dp);
|
|
|
// }
|
|
|
//
|
|
|
// public static int process2(int[] arr, int i, int j, int[][] dp) {
|
|
|
// if (j < 0) {
|
|
|
// return 0;
|
|
|
// }
|
|
|
// if (i == arr.length) {
|
|
|
// return j == 0 ? 1 : 0;
|
|
|
// }
|
|
|
// if (dp[i][j] != -1) {
|
|
|
// return dp[i][j];
|
|
|
// }
|
|
|
// int ans = process2(arr, i + 1, j, dp) + process2(arr, i, j - arr[i], dp);
|
|
|
// dp[i][j] = ans;
|
|
|
// return ans;
|
|
|
// }
|
|
|
//
|
|
|
public static int change3(int aim, int[] arr) {
|
|
|
int n = arr.length;
|
|
|
int[][] dp = new int[n + 1][aim + 1];
|
|
|
dp[n][0] = 1;
|
|
|
for (int i = n - 1; i >= 0; i--) {
|
|
|
for (int j = 0; j <= aim; j++) {
|
|
|
dp[i][j] = dp[i + 1][j];
|
|
|
if (j - arr[i] >= 0) {
|
|
|
dp[i][j] += dp[i][j - arr[i]];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return dp[0][aim];
|
|
|
}
|
|
|
|
|
|
public static int change4(int aim, int[] arr) {
|
|
|
int n = arr.length;
|
|
|
int[] dp = new int[aim + 1];
|
|
|
dp[0] = 1;
|
|
|
for (int i = n - 1; i >= 0; i--) {
|
|
|
for (int j = 0; j <= aim; j++) {
|
|
|
if (j - arr[i] >= 0) {
|
|
|
dp[j] += dp[j - arr[i]];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return dp[aim];
|
|
|
}
|
|
|
|
|
|
// public static int change5(int aim, int[] arr) {
|
|
|
// int n = arr.length;
|
|
|
// int[] dp = new int[aim + 1];
|
|
|
// dp[0] = 1;
|
|
|
// for (int i = n - 1; i >= 0; i--) {
|
|
|
// for (int j = arr[i]; j <= aim; j++) {
|
|
|
// dp[j] += dp[j - arr[i]];
|
|
|
// }
|
|
|
// }
|
|
|
// return dp[aim];
|
|
|
// }
|
|
|
|
|
|
}
|