LeetCode problem solution --518. Change exchange II (dp)

https://leetcode-cn.com/problems/coin-change-2/submissions/
Title:
Given a total amount of coins and different denominations. Function can be written to calculate the number of coins to make up the total amount of the composition. Assuming that each denomination coin has an infinite number.
Example 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

Note:
You can assume that:

0 <= amount (总金额) <= 5000
1 <= coin (硬币面额) <= 5000
硬币种类不超过 500 种
结果符合 32 位符号整数

Thinking

Expect to get the title dp, fully expect to see an unlimited number of coins knapsack problem (the value of each coin is 1, the cost for the coin, the total capacity amount), and then enter into a thinking, leading to the final did not write it down.

Positive Solution: Let f(i,j)代表拿前i种硬币,可以拼凑成j元的方案数字.
Recurrence relation as follows:

f(i,j) = f(i-1,j)+f(i,j-coins[j])		j >= coins[j]
f(i,j) = f(i-1,j)								i < coins[j]

Initialization problem:
along the lines of the backpack, initialize a two-dimensional array of dp, number line is the 0~coins.lengthnumber of column 0~amount+1.
When $ 0, no matter take several coins, are a number of programs.
Other cases 当前钱数%coins[i]==0, the program number is 1.

Code

public class Solution_518 {
    public static void main(String[] args) {
        change(5, new int[]{1, 2, 5});
    }

    public static int change(int amount, int[] coins) {
        int N = amount + 1;
        int[] weight = new int[coins.length + 1];
        for (int i = 1; i < weight.length; i++) {
            weight[i] = coins[i - 1];
        }
        int[][] dp = new int[weight.length][N];
        // 初始化
        for (int i = 0; i < weight.length; i++) {
            for (int j = 0; j < N; j++) {
                if (i == 0 && j != 0) {
                    dp[i][j] = 0;
                } else if (j == 0) {
                    dp[i][j] = 1;
                } else if (j % weight[i] == 0) {
                    dp[i][j] = 1;
                } else {
                    dp[i][j] = 0;
                }
            }
        }
        for (int i = 1; i < weight.length; i++) {
            for (int j = 1; j < N; j++) {
                if (j >= weight[i]) {
                    // 拿得起
                    dp[i][j] = dp[i][j - weight[i]] + dp[i - 1][j];
                } else {
                    // 拿不起
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[coins.length][amount];
    }
}

Optimization

Thinking f(i,j) = f(i-1,j)+f(i,j-coins[j]), current grid uses 上一轮次of the data f(i-1,j), and 当前轮次updated before the data f(i,j-coins[j]).
How one-dimensional array to represent the current two-dimensional array of it, that dp[i]represents dp[i-1][j]and dp[i-coins[j]]instead of dp[i][j-coins[j]]carefully think about, from the i=coinbeginning to traverse amount+1, that if you run into a dp [i] No updates dp[i]=dp[i] + dp[i-coin]right in dp[i]fact, is the last round the data, dp[i-coin]in fact, is updated before the current round of data.

In fact, optimization and knapsack problem, like a new one-dimensional dp array size amount+1.

Code

    public static int change(int amount, int[] coins) {
        int[] dp = new int[amount + 1];
        dp[0] = 1;
        for (int coin : coins) {
            for (int i = coin; i < amount + 1; i++) {
                dp[i] = dp[i] + dp[i - coin];
            }
        }
        return dp[amount];
    }

Guess you like

Origin blog.csdn.net/u012525096/article/details/92974388