LintCode刷题——换硬币

题目描述:

给出不同面额的硬币以及一个总金额. 写一个方法来计算给出的总金额可以换取的最少的硬币数量. 如果已有硬币的任意组合均无法与总金额面额相等, 那么返回 -1.

样例

样例1

输入:
[1, 2, 5]
11
输出: 3
解释: 11 = 5 + 5 + 1

样例2

输入: 
[2]
3
输出: -1

注意事项

你可以假设每种硬币均有无数个
总金额不会超过10000
硬币的种类数不会超过500, 每种硬币的面额不会超过100

 

思路:序列型动态规划

1、定义状态:dp[i] 表示拼出面值为i需要的最少硬币数

2、转移方程:dp[i] = min{dp[i], dp[i - coins[j]]+ 1}

3、初始值和边界:dp[0] = 0,为啥这里等于0,后面拼不出却设置为无穷大呢,其实这是有一定道理的,因为现实中,0是可以拼出来的,因为不给硬币即可做到,后面设置为无穷大是为了从中选出方案中最小的硬币数

4、计算返回dp[amount] ,不过题目明确说了,如果拼不出,则返回-1,所以最后还需再稍稍处理一下即可

 

AC代码:

 1 public class Solution {
 2     /**
 3      * @param coins: a list of integer
 4      * @param amount: a total amount of money amount
 5      * @return: the fewest number of coins that you need to make up
 6      */
 7     public int coinChange(int[] coins, int amount) {
 8         // write your code here
 9         if (coins == null || coins.length == 0) {
10             // 这还需要判断一下,因为可能你没有候选的硬币数,但是要让你拼出大于0的数,那么就拼不出了
11             if (amount <= 0) {
12                 return 0;
13             } else {
14                 // 这里的意思,其实就是说:比如你去店里买东西,忘了带钱,你身上一分都没
15                 // 但是老板依然让你给钱,不给不能走,此时的场景就好比你无论如何也拼不出的情况
16                 return -1;
17             }
18         } else {
19             // 如果存在硬币,但要拼的却是0,可以直接返回0即可
20             if (amount == 0) {
21                 return 0;
22             }
23         }
24 
25         // 定义状态:dp[i] 表示拼出面值为i需要的最少硬币数
26         int[] dp = new int[amount + 1];
27 
28         // 初始化
29         dp[0] = 0;
30 
31         // 转移方程 ,这里要从1开始,因为0在前面已经做了相关处理
32         // 现实中,0是可以拼出来的,因为不给硬币即可做到
33         for (int i = 1; i <= amount; i++) {
34             // 默认一开始都是拼不出来,这里将拼不出设置为无穷大
35             dp[i] = Integer.MAX_VALUE;
36             // 子问题:随便拿一个面值的硬币,将剩下的面值数交给更小的子问题去完成
37             // 如果此时要拼的面值小于此时拿的一个硬币的面值,那么就不拿这个硬币,换下一个硬币
38             // 且要保证剩下的面值数是能拼的出来的才行
39             // 枚举所有硬币
40             for (int j = 0; j < coins.length; j++) {
41                 if (i >= coins[j] && dp[i - coins[j]] != Integer.MAX_VALUE) {
42                     // 如果此时拿的硬币满足以上限制条件,那么就从满足条件的这些方案中选出拿硬币最少的
43                     // 如果当前的方案比之前的更好,则更新
44                     dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
45                 }
46             }
47         }
48 
49         // 返回结果,这里由于题目的要求,所以不能直接返回,要稍微做下处理,如果拼不出,则返回-1
50         if (dp[amount] == Integer.MAX_VALUE) {
51             return - 1;
52         }
53         return dp[amount];
54     }
55 }

 

posted @ 2021-03-30 11:19  没有你哪有我  阅读(80)  评论(0编辑  收藏  举报