int maxVal = 1000000000; // 把非法的值设置为我们期望方向的反方向
public int search(int idx, int amount, int[] coins)
{
if (amount == 0)
return 0;
if (amount < 0)
return maxVal; // 返会非常大的数,表示非法(不可以返回-1)
if (idx >= coins.length)
return maxVal; // 返会非常大的数,表示非法(不可以返回-1)
// 两种决策,(只使用某一号硬币,使用其他)
int a = search(idx, amount-coins[idx], coins) + 1;
int b = search(idx+1, amount, coins);
return Math.min(a,b);
}
public int coinChange(int[] coins, int amount)
{
int res = search(0, amount, coins);
if (res < maxVal)
{
return res;
}
else
{
return -1;
}
}
记忆化搜索改进:(还是会超时,因为amount可能会很大)
static int[][] f = new int[1000][1000000];
int maxVal = 1000000000; // 把非法的值设置为我们期望方向的反方向
int search(int idx, int amount, int[] coins)
{
if (amount == 0)
return 0;
if (amount < 0)
return maxVal; // 返会非常大的数,表示非法(不可以返回-1)
if (idx >= coins.length)
return maxVal; // 返会非常大的数,表示非法(不可以返回-1)
// 两种决策,(只使用某一号硬币,使用其他)
int a = search(idx, amount-coins[idx], coins) + 1;
int b = search(idx+1, amount, coins);
f[idx][amount] = Math.min(a,b);
return f[idx][amount];
}
public int coinChange(int[] coins, int amount)
{
// 初始化f数组
for (int i=0; i<1000; i++)
{
for (int j=0; j<1000000; j++)
{
f[i][j] = -1;
}
}
// 搜索
int res = search(0, amount, coins);
if (res < maxVal)
{
return res;
}
else
{
return -1;
}
}
改为迭代实现(自底向上计算):
用dp存储硬币数量,dp[i] 表示凑齐钱数 i 需要的最少硬币数,那么凑齐钱数 amount 最少硬币数为:
固定钱数为 coins[j] 一枚硬币,另外的钱数为 amount - coins[j] 它的数量为dp[amount - coins[j]],j 从0遍历到
coins.length - 1:
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
for (int i = 1; i <= amount; i++) {
dp[i] = 0x7fffffff;
for (int j = 0; j < coins.length; j++)
if (i >= coins[j] && dp[i - coins[j]] != 0x7fffffff) //①
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
return dp[amount] == 0x7fffffff ? -1 : dp[amount];
}