美文网首页
每日一题之零钱兑换

每日一题之零钱兑换

作者: this_is_for_u | 来源:发表于2020-05-01 22:33 被阅读0次

    题目322:零钱兑换

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

    示例1:

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

    示例2:

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

    说明:

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

    分析

    这题可以用贪心也可以用dp,这里使用dp方式,以示例1举例,如下图,有硬币[1, 2, 5],想要组成11,那就需要先组成(11-1, 11-2, 11-5),即(10, 9, 6),括号内为或关系,就是说想要组成11,那就需要先组成10或9或6,这里用dp存储组成x需要的硬币个数,则dp[11]= min(dp[10], dp[9], dp[6])+1,依此类推,dp[10] = min(dp[10-1], dp[10-2], dp[10-5]) + 1,这是从上向下类推,基本上从上向下类推的规律都可以从下向上推导,具体可以看代码啦。

    代码

    class Solution {
    public:
        int coinChange(vector<int>& coins, int amount) {
            if (amount == 0) return 0;
            // 如果没有任何一种硬币组合能组成总金额,返回 -1
            const int fail_value = -1;
            vector<int> dp(amount + 1, fail_value);
            std::sort(coins.begin(), coins.end());
            for (int i = 1; i <= amount; ++i) {
                for (auto coin : coins) {
                    if (i == coin) {
                        dp[i] = 1;
                        break;
                    }
                    if (i < coin) {
                        break;
                    }
                    if (dp[i-coin] != fail_value) {
                        if (dp[i] == fail_value) {
                            dp[i] = dp[i-coin] + 1;
                        } else {
                            dp[i] = min(dp[i-coin] + 1, dp[i]);
                        }
                    }
                }
            }
            return dp[amount];
        }
    };
    

    更多文章请关注公众号

    programmersmall.png

    相关文章

      网友评论

          本文标题:每日一题之零钱兑换

          本文链接:https://www.haomeiwen.com/subject/jpvcghtx.html