The sword refers to offer103: the minimum number of coins

Question:
Given coins of different denominations and a total amount. Write a function to calculate the minimum number of coins needed to make up the total amount. Returns -1 if none of the coin combinations make up the total amount.
You can think of an infinite amount of each type of coin.
Example 1:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3
Output: -1
Example 3 :
Input: coins = [1], amount = 0
Output: 0
Example 4:
Input: coins = [1], amount = 1
Output: 1
Example 5:
Input: coins = [1], amount = 2
Output: 2
Analysis :
Consider the coins of each denomination as an item, and the target amount as the capacity of the backpack, then this problem is equivalent to finding the minimum number of items when the backpack is full. It is worth noting that the coins of each denomination can be used any number of times, so the problem is no longer a 0-1 knapsack problem, but an unbounded knapsack problem. (also called the complete knapsack problem)
Use the function f(i,j) to denote the minimum number of coins required for the first i coins (coins[0,...,i-1]) to make up a total of j. When using 0 coins labeled i-1, f(i,j)=f(i-1,j), when using a coin labeled i-1, f(i,j) is equal to f(i-1,j-coins[i-1] )+1, and so on. When using k coins labeled i-1, f(i,j) is equal to f(i-1,jk coins[i-1])+k (using the first i-1 coins The minimum number of coins required to make up the total amount jk coins[i-1], and then assume k coins labeled i-1), since the goal is to find the minimum number of coins, f(i, j) is the above Minimum of all cases:
insert image description here
If there are n coins and the target total is t, then f(n,t) is the solution to the problem.
When j=0, that is, the total amount is 0, f(i, 0)=0, that is, 0 coins are selected from the first i types of coins, so that the total amount is equal to 0. When i is equal to 0 and j is greater than 0, that is It is obviously impossible to use 0 coins to make a total greater than 0, so a special value can be used instead.
The second idea:
insert image description here
It is equivalent to calculating from right to left horizontally. This method is similar to counting from top to bottom. After one column is calculated, the next column is calculated, and the function f(i) is used to indicate the minimum amount of coins required to make up a total of i. It should be noted that this function has only one parameter i representing the total amount of coins. If the target total amount is t, then f(t) is the solution of the whole problem.
Code:

import java.util.Arrays;

public class CoinChange {
    
    
//    第一种思路
    public int coinChange1(int[] coins, int amount) {
    
    
        int[] dp = new int[amount+1];
        Arrays.fill(dp,amount+1);
        dp[0] = 0;
        for (int coin : coins) {
    
    
            for (int j = amount; j >=1; j--) {
    
    
                for (int k = 1; k*coin <=j; k++) {
    
    
                    dp[j] = Math.min(dp[j],dp[j-k*coin]+k);
                }
            }
        }
        return dp[amount] > amount ?-1:dp[amount];
    }
//    第二种思路
//
    public int coinChange2(int[] coins, int amount){
    
    
        int[] dp = new int[amount+1];
//        i代表总额,dp[i]代表凑出总额为i的最少硬币数目
        for (int i = 1; i <=amount; i++) {
    
    
            dp[i] = amount+1;
            for (int coin:coins){
    
    
//                如果总额度大于等于该硬币的值
                if (i>=coin){
    
    
                    dp[i] = Math.min(dp[i],dp[i-coin]+1);
                }
            }
        }
        return dp[amount]>amount ?-1:dp[amount];
    }
}

insert image description here

Guess you like

Origin blog.csdn.net/Jiaodaqiaobiluo/article/details/123336382