02Leetcode每日一题——零钱兑换
题目
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
分析
很容易想到用动态规划解决,在此之前先写个暴力递归观察一下。
核心思路就是:总数是amount,数组是coins,用每个coins中的硬币试试看能不能组成最终的解。假如硬币数组是[1, 2, 5],总数是11,我们先用1试试,即11 - 1,得到10,看看10能不能用数组组合成功,或者得到的值最小。
所以主要递归是:coinChange(coins, amount-coin);
迭代次数就是硬币数组的总数
边界条件是:
- amount<0时,说明此方案不可行,返回-1
- amount = 0时,说明此方案刚刚得到结果,返回0
- 如果遍历完
count
值还是正无穷,说明当前的这个amount均不可行,返回-1
代码如下:
class Solution {
public int coinChange(int[] coins, int amount) {
if(amount < 0){
return -1;
}
if(amount == 0) return 0;
int count = Integer.MAX_VALUE;
for(int coin : coins){
int coinResult = coinChange(coins, amount-coin);
if(coinResult > -1) count = coinResult+1<count?coinResult+1:count;
}
return count==Integer.MAX_VALUE?-1:count;
}
}
至上而下的动态规划
基本上是递归的分析思路,需要增加一个数组进行结果保存
class Solution {
private int[] data = null;
public int coinChange(int[] coins, int amount) {
if(data==null) {
data = new int[amount+1];
Arrays.fill(data, -2);
}
if(amount < 0){
return -1;
}
if(amount == 0) return 0;
if(data[amount]>-2) return data[amount];
int count = Integer.MAX_VALUE;
for(int coin : coins){
int coinResult = coinChange(coins, amount-coin);
if(coinResult > -1) count = coinResult+1<count?coinResult+1:count;
}
int result = count==Integer.MAX_VALUE?-1:count;
data[amount] = result;
return result;
}
}