import java.util.HashMap;
/*
* 给定数组arr, arr中所有的值都为正数且不重复。 每个值代表一种面值的货币,
* 每种面值的货币可以使用任意张, 再给定一个整数aim代表要找的钱数, 求换钱有多少种方法。
*
* 举例:
* arr=[5,10,25,1], aim=0。组成0元的方法有1种, 就是所有面值的货币都不用。 所以返回1。
* arr=[5,10,25,1], aim=15。组成15元的方法有6种, 分别为3张5元、 1张10元+1张5元、
* 1张10元+5张1元、 10张1元+1张5元、 2张5元+5张1元和15张1元。 所以返回6。
* arr=[3,5], aim=2。任何方法都无法组成2元。 所以返回0。
*/
public class FindAimInArr {
public static void main(String[] args) {
int[] arr = new int[] {
25, 20, 10, 5, 1 };
System.out.println(coins(arr, 50));----打印71
System.out.println(coins2(arr, 50));----打印71
System.out.println(coins3(arr, 50));----打印71
}
// 例子:arr[200,100,50,20,5,1] aim=100
// 方法一:暴力递归、
// 方法二:通过一个Map缓存优化暴力递归、
// 方法三:动态规划--------------解决子问题重叠问题
// 方法一:暴力递归、
public static int coins(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
return process(arr, 0, aim);
}
// int[] arr:不变的变量,面试数组
// index:可以任意自由使用index及其之后所有的钱
// aim:目标钱数
// 返回值:方法数
public static int process(int[] arr, int index, int aim) {
int res = 0;
if (index == arr.length) {
res = aim == 0 ? 1 : 0;
} else {
for (int zhang = 0; arr[index] * zhang <= aim; zhang++) {
res += process(arr, index + 1, aim - zhang * arr[index]);
}
}
return res;
}
// 方法二:通过一个Map缓存优化暴力递归---记忆化搜索方法
public static int coins2(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
return process_map(arr, 0, aim);
}
// key:"index_aim"
// value:返回值
public static HashMap<String, Integer> map = new HashMap<>();
public static int process_map(int[] arr, int index, int aim) {
int res = 0;
if (index == arr.length) {
res = aim == 0 ? 1 : 0;
} else {
for (int zhang = 0; arr[index] * zhang <= aim; zhang++) {
int nextAim = aim - arr[index] * zhang;
String key = String.valueOf(index + 1) + "_" + String.valueOf(nextAim);
if (map.containsKey(key)) {
res += map.get(key);
} else {
res += process_map(arr, index + 1, nextAim);
}
}
}
map.put(String.valueOf(index) + "_" + String.valueOf(aim), res);
return res;
}
// 方法三:动态规划--------------解决子问题重叠问题
public static int coins3(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
return process_dp(arr, aim);
}
public static int process_dp(int[] arr, int aim) {
int[][] dp = new int[arr.length][aim + 1];
for (int i = 0; i < arr.length; i++) {
dp[i][0] = 1;
}
for (int j = 1; arr[0] * j <= aim; j++) {
dp[0][arr[0] * j] = 1;
}
for (int i = 1; i < arr.length; i++) {
for (int j = 1; j <= aim; j++) {
dp[i][j] = dp[i - 1][j];
dp[i][j] += j - arr[i] >= 0 ? dp[i][j - arr[i]] : 0;
}
}
return dp[arr.length - 1][aim];
}
}
暴力递归到动态规划
猜你喜欢
转载自blog.csdn.net/weixin_44374871/article/details/98209949
今日推荐
周排行