标签:++ ems 推出 自底向上 思路 不同 位数组 com 个数
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回?-1。
这种题是很明显的动态规划。
我对动态规划不是特别熟练,因此第一时间没有思路,想的是一个二维的数组,发现并不能推出结果。我在草稿纸上画了一下写出了一个一位数组的状态转移方程:
dp[i] = min(dp[i],dp[i-coins[j]]+1)
这是一个自底向上方法,这样的状态转移方程是可以求出结果的,但是需要注意一些细节、边界问题。
我的代码是这样的
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
if(amount==0) return 0;
if(amount<0) return -1;
sort(coins.begin(),coins.end());
int len = coins.size();
if(len==0) return -1;
vector<int> dp(amount+1,amount+1);
for(int i=0;i<len;i++)
{
if(coins[i]<=amount) dp[coins[i]] = 1;
}
for(int i=coins[0];i<=amount;i++)
{
for(int j=0;j<len;j++)
{
if(coins[j]<=i)
{
dp[i] = min(dp[i],dp[i-coins[j]]+1);
}
}
}
// return dp[amount];
return dp[amount]!=amount+1?dp[amount]:-1;
}
};
但是我更好奇的是自顶向下方法。原来,官方题解提供的自顶向下方法其实是利用递归来实现的,利用了递归函数栈先进后出的特性。
class Solution {
vector<int>count;
int dp(vector<int>& coins, int rem) {
if (rem < 0) return -1;
if (rem == 0) return 0;
if (count[rem - 1] != 0) return count[rem - 1];
int Min = INT_MAX;
for (int coin:coins) {
int res = dp(coins, rem - coin);
if (res >= 0 && res < Min) {
Min = res + 1;
}
}
count[rem - 1] = Min == INT_MAX ? -1 : Min;
return count[rem - 1];
}
public:
int coinChange(vector<int>& coins, int amount) {
if (amount < 1) return 0;
count.resize(amount);
return dp(coins, amount);
}
};
标签:++ ems 推出 自底向上 思路 不同 位数组 com 个数
原文地址:https://www.cnblogs.com/AAAHQZ/p/12444889.html