BM70 兑换零钱(一)

描述

给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。

如果无解,请返回-1.


数据范围:数组大小满足 Java练习题—动态规划(九)_数组 , 数组中每个数字都满足 Java练习题—动态规划(九)_数组_02Java练习题—动态规划(九)_数组_03


要求:时间复杂度 Java练习题—动态规划(九)_整型_04 ,空间复杂度 Java练习题—动态规划(九)_整型_05


示例1

输入:

[5,2,3],20
  • 1.

返回值:

4
  • 1.

示例2

输入:

[5,2,3],0
  • 1.

返回值:

0
  • 1.


Java代码

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 最少货币数
     * @param arr int整型一维数组 the array
     * @param aim int整型 the target
     * @return int整型
     */
    // 思路:将要找的钱数aim看作背包容量,将货币面值看作石头重量,求将容量为aim的背包装满
    // 的最少货币数
    public int minMoney (int[] arr, int aim) {
        // write code here
        // dp[i]表示组成要找的钱数i时的最少货币数
        int[] dp = new int[aim + 1];
        // 要找的钱数为0时,最少的货币数为0,所以初始化dp[0]=0
        dp[0] = 0;
        int max = Integer.MAX_VALUE;
        // 将要找钱数1~aim对应的最少货币数初始化为int的最大值,防止在递推过程中Math.min时
        // 取到错误值
        for (int k = 1; k < aim + 1; k++) {
            dp[k] = max;
        }
        // 遍历,在组合中添加将面值arr[i]的货币,使得组合总额==要找的钱数,用dp[j]记录最少
        // 货币数
        for (int i = 0; i < arr.length; i++) {
            for (int j = arr[i]; j <= aim; j++) {
                // dp[j - arr[i]] == max表示dp[j - arr[i]]对应要找的钱数!=组合的钱数总额
                // 此时在往组合中添加货币arr[i]也不能使得新的组合钱数总额=要找的钱数
                if (dp[j - arr[i]] != max) {
                    // 递推公式:比较上一轮i循环得到的最少货币数组合dp[j]和当前循环得到的j
                    // 的最少货币数组合dp[j - arr[i]] + 1,取较小值。dp[j - arr[i]]表示
                    // 要找钱数j-arr[i]的最少货币组合,j - arr[i]+arr[i]=j,即往dp[j - arr[i]]
                    // 对应的组合中加入货币arr[i]后,组合的货币总额等于要找的钱数j,新增了1个货币
                    // arr[i],所以此时的dp[j]=dp[j - arr[i]] + 1
                    dp[j] = Math.min(dp[j], dp[j - arr[i]] + 1);
                }
            }
        }
        if (dp[aim] == max) return -1;
        else return dp[aim];
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.


import java.util.*;

public class Solution {
    public int minMoney (int[] arr, int aim) {
        // 凑成i块钱所需要的最少货币数
        int[] dp = new int[aim + 1];
        Arrays.fill(dp, aim + 1);
        // 凑成0元需要0个货币数
        dp[0] = 0;
        // 先遍历货币
        for (int c : arr) {
            // 后根据货币数值遍历目标金额
            for (int i = c; i <= aim; i++) {
                // 将当前货币加入
                // 不将当前货币加入
                // 取个最小值
                dp[i] = Math.min(dp[i - c] + 1, dp[i]);
            }
        }
        // 如果目标金额的所需最少货币数是aim+1,说明凑不成aim
        return dp[aim] == aim + 1 ? -1 : dp[aim];
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.