文章目录
- 1. 题目信息
- 2. 解题
- 2.1 回溯穷举
- 2.2 动态规划
1. 题目信息
给定不同面额的硬币 coins 和一个总金额 amount。
编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1示例 2:
输入: coins = [2], amount = 3
输出: -1说明:
你可以认为每种硬币的数量是无限的。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
类似题目:LeetCode 518. 零钱兑换 II(动态规划)
2.1 回溯穷举
超时
class Solution//回溯
{
public:int coinChange(vector<int>& coins, int amount){int minPieces = INT_MAX;money(coins, amount, 0, 0, minPieces);if(minPieces != INT_MAX)return minPieces;elsereturn -1;}void money(vector<int>& coins, int &amount, long curMoney, int curPieces, int &minPieces){if(curMoney > amount){curPieces = INT_MAX;//表示不存在return;}if(curMoney == amount){if(curPieces < minPieces)minPieces = curPieces;return;}for(int i = 0; i < coins.size(); ++i){money(coins, amount,curMoney+coins[i], curPieces+1, minPieces);}}
};
2.2 动态规划
states[i]表示找 i 元需要的最少张数
那么states[i] = min{states[i-coins[j]] | j = 0,1,…coins.size() }+1
class Solution {
public:int coinChange(vector<int>& coins, int amount) {if(amount < 1)return 0;int states[amount+1];int i, j;for(i = 0; i <= amount; ++i)states[i] = amount+1;//找i元钱,不可能需要amount+1张states[0] = 0;for(i = 0; i <= amount; ++i){for(j = 0; j < coins.size(); ++j){if(i-coins[j] >= 0 && states[i] > states[i-coins[j]]+1){states[i] = states[i-coins[j]]+1;}}}if(states[amount] != amount+1)return states[amount];elsereturn -1;}
};
class Solution { //2020.3.8
public:int coinChange(vector<int>& coins, int amount) {if(amount <= 0)return 0;int n = coins.size(), j, m;vector<int> dp(amount+1, INT_MAX);dp[0] = 0;for(j = 0; j <= amount; ++j)//遍历所有的金额数{if(dp[j] != INT_MAX){for(m = 0; m < n; ++m){if(j <= amount-coins[m])dp[j+coins[m]] = min(dp[j]+1, dp[j+coins[m]]);}}}if(dp[amount] != INT_MAX)return dp[amount];return -1;}
};