leetcode-322. 零钱兑换

题目地址:

https://leetcode-cn.com/problems/coin-change/

 

322. 零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。
编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
如果没有任何一种硬币组合能组成总金额,返回 -1。 你可以认为每种硬币的数量是无限的。 示例 1: 输入:coins = [1, 2, 5], amount = 11 输出:3 解释:11 = 5 + 5 + 1
示例
2: 输入:coins = [2], amount = 3 输出:-1
示例
3: 输入:coins = [1], amount = 0 输出:0

示例 4: 输入:coins = [1], amount = 1 输出:1
示例
5: 输入:coins = [1], amount = 2 输出:2 提示: 1 <= coins.length <= 12 1 <= coins[i] <= 231 - 1 0 <= amount <= 104 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/coin-change 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {

    }
};

 

 

 

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int MAX = amount+1;//确定好零钱最大个数
        vector<int> dp(amount+1, MAX);//申请amount+1个空间,都赋值为MAX
        dp[0] = 0;
        for(int i=1;i<=amount;i++)
        {
            for(int j=0;j<coins.size();j++)
            {
                if(coins[j]<=i) // 硬币值小于当前的金额
                {
                    dp[i] = min(dp[i], dp[i-coins[j]]+1); //核心的状态转移方程
                }
            }
        }
        return dp[amount]>amount ? -1:dp[amount];
    }
};
请先思考如何做,再来看答案

 



例如:

coins[1,2,5]
amount=11
dp[11]=MAX=amount+1

 

先构造一个dp数组,长度是amount+1,给每个元素赋值为 最大值。这里可以设定这个最大值为 amount+1。

再赋初值,设置dp[0]=0,表示amount为0的时候,需要的硬币个数为零。

 

dp[]数组解释:

这里的dp[]数组存的就是每个金额对应的最少硬币数。存的就是最终的解。

比如dp[6]=X,表示 总金额为6的时候,需要X个硬币。

dp[]数组是不断往后确定下去的,直到amount位置。 

 

看下图,每一列的dp[],当amount=X的时候,dp[X]的值就确定了下来。

比如,amount=1的时候,dp[1]就确定了,此时dp[2]、dp[3]等等还是初始的最大值,是未确定的。

amount=2的时候,dp[2]就确定了,此时dp[3]、dp[4]等等还是初始的最大值,是未确定的。

这些已经确定下来的dp值,在amount 继续变大的时候,这些值是不会再变的。

比如amount=5, dp[1]依然是1,所以你会看到每一列的颜色不同,但是值是固定下来的。

dp[1]表示的仅仅是amount=1的时候,最小硬币数。 

 

 

一定要动手一步一步推导一下,这样才能加深印象。否则,今天看懂了,过了2天,又忘记怎么写了。

手动一步一步推导,深入到细节,理解会更深刻。

 

分析步骤如下:

初始值,amount = 0:

dp[0] = 0,表示 总金额为0的时候,需要0个硬币。

 

牢记状态转移方程: dp[i] = min(dp[i], dp[i-coins[j]]+1); //核心的状态转移方程

我们一步一步来 推导、分析:

 

amount=1

dp[1] 为 MAX

for循环遍历coins硬币数组

dp[1 - 1] =dp[0]=0

根据状态转移方程,dp[1] = 1

 

amount=2

dp[2]为 MAX 

for循环遍历coins硬币数组

 dp[2-1] = dp[1] = 1

dp[2 -2] =dp[0] =0

根据状态转移方程,dp[2] = 1

 

amount=3

dp[3]为 MAX 

for循环遍历coins硬币数组

 dp[3-1] = dp[2] = 1

dp[3 -2] =dp[1] =1

根据状态转移方程,dp[3] = 2

 

 

amount=4

dp[4]为 MAX 

for循环遍历coins硬币数组

 dp[4-1] = dp[3] = 3

dp[4 -2] =dp[2] =1

根据状态转移方程,dp[4] = 2  (很多人以为这里会是3哦,其实是2)

 

 

amount=5

dp[5]为 MAX 

for循环遍历coins硬币数组

 dp[5-1] = dp[4] = 2

dp[5 -2] = dp[3] = 2

dp[5-5] = dp[0] = 0

根据状态转移方程,dp[5] = 1

 

 

amount=6

dp[6]为 MAX 

for循环遍历coins硬币数组

 dp[6-1] = dp[5] = 1

dp[6 -2] = dp[4] = 2

dp[6-5] = dp[1] = 1

根据状态转移方程,dp[6] = 2

 

 

amount=7

dp[7]为 MAX 

for循环遍历coins硬币数组

 dp[7-1] = dp[6] = 2

dp[7 -2] = dp[5] = 1

dp[7-5] = dp[2] = 1

根据状态转移方程,dp[7] = 2

 

 

amount=8

dp[8]为 MAX 

for循环遍历coins硬币数组

 dp[8-1] = dp[7] = 2

dp[8 -2] = dp[6] = 2

dp[8-5] = dp[3] = 2

根据状态转移方程,dp[8] = 3

 

 

amount=9

dp[9]为 MAX 

for循环遍历coins硬币数组

 dp[9-1] = dp[8] = 3

dp[9 -2] = dp[7] = 2

dp[9-5] = dp[4] = 2

根据状态转移方程,dp[9] = 3

 

 

amount=10

dp[10]为 MAX 

for循环遍历coins硬币数组

 dp[10-1] = dp[9] = 3

dp[10 -2] = dp[8] = 3

dp[10-5] = dp[5] = 1

根据状态转移方程,dp[10] = 2

 

 

amount=11

dp[11]为 MAX 

for循环遍历coins硬币数组

 dp[11- 1] = dp[10] = 2

dp[11 -2] = dp[9] = 3

dp[11 - 5] = dp[6] = 2

根据状态转移方程,dp[11] = 3

 

posted @ 2020-12-22 08:24  He_LiangLiang  阅读(117)  评论(0编辑  收藏  举报