322. Coin Change零钱兑换问题

1.

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

示例 1:

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

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

解法:背包问题,首先想最少的硬币数,肯定是尽量取较大的硬币,能取一个则硬币数加一,取当前硬币的个数等于之前硬币个数加上当前这个硬币(也就是加1),但前提是之前硬币总价值加上当前这个硬币的价值不能超过总个数,因此是一个动态规划问题。
状态转移方程:
因此两层循环,外面一层是金额,里面一层是每个硬币。
d p [ i ] = m i n ( d p [ i ] , d p [ i c o i n [ j ] ] + 1 ) dp[i]=min(dp[i],dp[i-coin[j]]+1)

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount+1,amount+1);
        dp[0] = 0;
        for(int i=1;i<=amount;i++){//这里从1开始到<=,是因为第一个数量为0值肯定为0,最后一个数量肯定也要涉及到
            for(int j=0;j<coins.size();j++){
                if(coins[j]<=i)
                    dp[i] = min(dp[i],dp[i-coins[j]]+1);
            }
        }
        return dp.back()>amount?-1:dp.back();
    }
};

2.

给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。

示例 1:

输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例 2:

输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额2的硬币不能凑成总金额3。
示例 3:

输入: amount = 10, coins = [10]
输出: 1

解题:这道题和上一个非常相似,思想难度也不大,但是有一个坑,就是顺序问题,例如总金额4,121和112都是总金额4,但是要求是无序的,也就是说这两个都是一个情况,所以不能像之前那样考虑,因为外循环金额内循环硬币,121和112都是在最后一个硬币循环遇到的,肯定会重复,怎么不会重复呢?外循环硬币内循环金额就可以了,这是为啥呢?就相当于一个硬币一个硬币的加,每增加一个硬币就从1到amount考虑所有金额,因为硬币是一个一个考虑了,所以就不会重复了。

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<int> dp(amount+1,0);
        dp[0] = 1;
        for(int j=0;j<coins.size();j++){
            for(int i=1;i<=amount;i++){
                if(coins[j]<=i){
                    dp[i] += dp[i-coins[j]];
                }
            }
        }
        return dp.back();
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43554642/article/details/88957260