[leetcode]322.零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

示例 1:

输入: coins = [1, 2, 5], amount = 11
输出: 3 
解释: 11 = 5 + 5 + 1

示例 2:

输入: coins = [2], amount = 3
输出: -1

说明:
你可以认为每种硬币的数量是无限的。

思路:
dfs+贪心:

首先题目要求总金额最小的硬币个数,则贪心策略一定是先放入最大的硬币,并且尽可能多的放,直到放不下,之后再去寻找小面值的硬币,如果小面值的硬币不能满足要求,则回溯,逐个减少大面值的硬币的个数,到满足条件,当面值符合要求,判断当前硬币的个数是否比保存的最小的个数少,如果是,则更新。

优化剪枝:在dfs递归过程中,如果发现当前已经使用的硬币个数已经多余保存的最小个数,则当前这一组一定不可能是答案,即不用继续下去。

AC代码:

class Solution {
   public:
    void dfs(vector<int>& coins, int amount, int c_index, int count, int& ans) {
        if (amount == 0) {
            ans = min(ans, count);
            return;
        }
        if (c_index == coins.size()) return;//使用完了所有的硬币
        for (int k = amount / coins[c_index]; k >= 0 && k + count < ans; k--) {
        	//逐步回溯,只有当k+count
            dfs(coins, amount - k * coins[c_index], c_index + 1, count + k,
                ans);
        }
    }
    int coinChange(vector<int>& coins, int amount) {
        if (amount == 0) return 0;
        sort(coins.begin(), coins.end());
        reverse(coins.begin(), coins.end());
        int ans = INT_MAX;
        dfs(coins, amount, 0, 0, ans);
        if (ans == INT_MAX)
            return -1;
        else
            return ans;
    }
};

思路2:
动态规划,可以看成背包容量无限,每件货物质量为1的完全背包问题。
定义dp数组,其中dp[i]表示达到价值i所需要的最少的货币。
对每一个i,遍历所有可能使用的硬币j,则dp[i]即为使用j号硬币+要达到i-coins[j]所需要的最少硬币,
最终去一个最小的dp[i]保存。
如题目中样例coins = [1, 2, 5], amount = 11
所需要计算dp[11],而dp[11]=min(dp[11-1],dp[11-2],dp[11-5])+1.

AC代码:(C++)

class Solution {
   public:
    int coinChange(vector<int>& coins, int amount) {
        if (amount == 0) return 0;
        int size = coins.size();
        vector<int> dp(amount + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < size; j++) {
                if (coins[j] <= i) {
                    int remain = i - coins[j];//使用j号硬币之后还需要多少钱才能凑够i
                    if (dp[remain] != INT_MAX)
                        dp[i] = min(dp[i], dp[remain] + 1);
                }
            }
        }
        if (dp[amount] == INT_MAX)
            return -1;
        else
            return dp[amount];
    }
};

你可能感兴趣的:(LeetCode)