LeetCode 刷题记录帖(322,零钱兑换)

题目的链接如下:https://leetcode-cn.com/problems/coin-change/

----------------------------------------------------------------------------------------------------------------------------

题目:

给定不同面额的硬币 coins 和一个总金额 amount。

编写一个函数来计算可以凑成总金额所需的最少的硬币个数。

如果没有任何一种硬币组合能组成总金额,返回 -1

 

示例 1:

输入:coins=[1, 2, 5], amount = 11

输出:3

解释: 11 = 5 + 1 + 1

示例 2:

输入:coins=2, amount = 3

输入:-1

----------------------------------------------------------------------------------------------------------------------------

思路1:

首先排除贪心算法,因为如果是贪心算法,这道题的难度不会是中等(滑稽)。

简单思考一下,如果是贪心算法的话,如:coins = 1,8,9,amount=16。

贪心算法结果为:9+1+1+1+1+1+1+1 = 16,输出8,但是实际:8+8=16,输出2。

然后由此想到穷举法 -> 再想到递归,这样一来,这道题肯定是有思路解决了(几乎所有问题都是可以穷举的),但是,这样一来就会消耗很多资源,在leetcode提交是肯定会超时的。

思路2:

这道题和背包问题是一样的,就拿示例1来看,我们可以把amount=11,拆分成amount=0,1,2,3....来一步一步求解。

假设结果为x

  • 首先amount=0的时候,输出肯定是0,即有0种组合。(x=0)
  • amount=1的时候,可以遍历3枚硬币,判断是否拿这一枚
    • 如果拿硬币1,那么amount=1-1=0,然后看当amount=0的时候,它的最优解是多少,由上面可得,amount=0的时候,最优解是0,所以现在的最优解是1+0=1,有1种组合(x=1)
    • 如果拿硬币2,那么amount=1-2=-1,不满足条件
    • 如果拿硬币5,那么amount=1-5=-4,不满足条件
    • 得出amount=1的时候,最优解为1。(即x=1)
  • amount=2的时候,遍历3枚硬币。
    • 如果拿硬币1,那么amount=2-1=1,然后看当amount=1的时候,它的最优解是多少,由上面可得,amount=1的时候,最优解是1,所以现在的最优解是1+1=2,有2种组合。(最优解:x=2)
    • 如果拿硬币2,那么amount=2-2=0,然后看当amount=2的时候,它的最优解是多少,由上面可得,amount=0的时候,最优解是0,所以现在的最优解是1+0=1,有1种组合。(最优解:x=1)
    • 如果拿硬币5,那么amount=2-5=-3,不满足条件       
    • 得出amount=2的时候,最优解为1。(即x=1)。(1<2,肯定取小的那个啦)

amount=3的时候,遍历3枚硬币。

  • 如果拿硬币1,那么amount=3-1=2,然后看当amount=2的时候,它的最优解是多少,由上面可得,amount=2的时候,最优解是1,所以现在的最优解是1+1=2,有2种组合。(最优解:x=2)
  • 如果拿硬币2,那么amount=3-2=1,然后看当amount=1的时候,它的最优解是多少,由上面可得,amount=1的时候,最优解是1,所以现在的最优解是1+1=2,有1种组合。(最优解:x=2)
  • 如果拿硬币5,那么amount=3-5=-2,不满足条件     
  • 得出amount=3的时候,最优解为2。(即x=2)。
  • amount=4的时候,遍历3枚硬币。
    • 如果拿硬币1,那么amount=4-1=3,然后看当amount=3的时候,它的最优解是多少,由上面可得,amount=3的时候,最优解是2,所以现在的最优解是1+2=3,有3种组合。(最优解:x=3)
    • 如果拿硬币2,那么amount=4-2=2,然后看当amount=2的时候,它的最优解是多少,由上面可得,amount=2的时候,最优解是1,所以现在的最优解是1+1=2,有2种组合。(最优解:x=2)
    • 如果拿硬币5,那么amount=4-5=-1,不满足条件     
    • 得出amount=4的时候,最优解为2。(即x=2)。(因为2<3)

...

...

...

(剩下的就不分析了,大家可以自己拿草稿纸演算一下,如果对背包问题比较熟悉的同学,思路应该很清晰了,如果不熟悉,建议去看一下背包问题,那个是非常经典的一个题目)

附上代码:(直接从LeetCode的编辑框粘贴过来的)

class Solution {
public:

    int coinChange(vector& coins, int amount) {
        if (amount < 0 || coins.size() == 0) return -1;
        if (amount == 0) return 0;
        int memory[amount + 1]; // 定义一个数组,用来存放每一步的最优解
        memory[0] = 0; // 初始化,因为amount=0的时候,必定为0
        for (int i=1; i<=amount; ++i) {
             // 定义一个临时变量,用于存放每一步amount,在遍历硬币数组时候的最小值,即暂存每一步的最优解
            int min = INT_MAX; 
            for (int j=0; j= 0 && memory[i-coins[j]] < min) {   
                    // 自底向上搜索,如果还剩i元,在减去 coins[j]元的时候,即以前的“经验值”,数量小于当前的最小值
                    min = memory[i-coins[j]] + 1;
                }
            }
            memory[i] = min;
        }
        return memory[amount] == INT_MAX ? -1 : memory[amount];
    }

};

 

 

你可能感兴趣的:(算法,LeetCode,背包问题)