zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    form表单介绍
    if条件语句
    表格.html
    列表.html
    CSS Js链接HTML文件
    DQL
    mysql介绍
    第一次接触mysql
    逻辑运算、作用域问题、DOM
    Js数据类型具体分析
  • 原文地址:https://www.cnblogs.com/music-liang/p/14171169.html
Copyright © 2011-2022 走看看