• [LeetCode] 518. Coin Change 2 硬币找零 2


    You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin.

    Note: You can assume that

    • 0 <= amount <= 5000
    • 1 <= coin <= 5000
    • the number of coins is less than 500
    • the answer is guaranteed to fit into signed 32-bit integer

    Example 1:

    Input: amount = 5, coins = [1, 2, 5]
    Output: 4
    Explanation: there are four ways to make up the amount:
    5=5
    5=2+2+1
    5=2+1+1+1
    5=1+1+1+1+1 

    Example 2:

    Input: amount = 3, coins = [2]
    Output: 0
    Explanation: the amount of 3 cannot be made up just with coins of 2.
    

    Example 3:

    Input: amount = 10, coins = [10] 
    Output: 1

    给定一些不同面值的硬币,和一个钱数。编写函数计算要得到目标金额有多少种不同的硬币组合方式。

    322. Coin Change 的变形,322题是求最少能用几个硬币组成给的钱数,而这题求的是组成给定钱数总共有多少种不同的方法。

    解法:动态规划DP, 建立dp数组,保存能到达当前amount的步数。逐个金额遍历,看只用前i个金额能到达j的步数有多少,实现方法是累加起来dp[当前amount - 第i个金额],最后返回dp[amount]。

    State: dp[i], 表示总额为i时的方案数

    Function: dp[i] = Σdp[i - coins[j]],  表示总额为i时的方案数 = 总额为i-coins[j]的方案数的加和

    Initialize: dp[0] = 1, 表示总额为0时方案数为1

    Retrun: dp[n] or dp[-1]

    Java:

    public class Solution {  
        public int change(int amount, int[] coins) {  
            if (coins == null || coins.length == 0) {  
                return amount == 0? 1: 0;  
            }  
            int[] dp = new int[amount + 1];  
            dp[0] = 1;  
            for (int i = 0; i < coins.length; i ++) {  
                for (int j = 1; j <= amount; j ++) {  
                    if (j >= coins[i]) {  
                        dp[j] += dp[j - coins[i]];  
                    }  
                }  
            }  
            return dp[amount];  
        }  
    }   

    Python:

    class Solution(object):
        def change(self, amount, coins):
            """
            :type amount: int
            :type coins: List[int]
            :rtype: int
            """
            dp = [0] * (amount + 1)
            dp[0] = 1
            for c in coins:
                for x in range(c, amount + 1):
                    dp[x] += dp[x - c]
            return dp[amount] 

    扩展思考:将上述代码中的循环顺序对调,即为求不同硬币的排列数(Permutation)

    class Solution(object):
        def change(self, amount, coins):
            """
            :type amount: int
            :type coins: List[int]
            :rtype: int
            """
            dp = [0] * (amount + 1)
            dp[0] = 1
            for x in range(amount + 1):
                for c in coins:
                    if c > x: continue
                    dp[x] += dp[x - c]
            return dp[amount]  

    C++:

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

    类似题目:

    [LeetCode] 322. Coin Change 硬币找零

    [CareerCup] 9.8 Represent N Cents 组成N分钱

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    ubuntu12.04.2上利用cmake安装opencv2.4.6
    微软无线鼠标3500滚轮问题
    Linux 安装 Tomcat
    Linux 安装 MySQL
    Linux 安装 JDK
    Linux 安装 Redis 及踩坑
    IDEA Git 撤销push(回退到指定版本)
    【Java】Ajax实现级联城市
    node.js更换镜像源
    【Java】数据库连接池的简单使用
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8674222.html
Copyright © 2020-2023  润新知