322. Coin Change

1. 题目描述
题目链接

You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
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
Note:
You may assume that you have an infinite number of each kind of coin.

2. 题目分析
硬币找零问题,经典的动态规划问题。给定一个金额,和给定几种面值确定的硬币,并且硬币数量无限,找出使用最少的硬币数来凑齐想要的金额。
人类的的思维,肯定是,一开始使用最大面额的硬币去算,然后多了就换小一点的面额,少了,就换大一点的面额,直到等于金额,或者发现无法凑齐整数的金额,则结束。但计算机无法像人类这样智能,可以准确知道少了多少面额,然后搜索是否有相应的硬币去凑。而是要一个个去试和比较,这样的话时间复杂度更高,所以我们不采用这种方法。
根据条件找最优解,并且能够不断拆分成相同的小问题,所以动态规划的思想,自上而下分析。比如说 coins = [1, 2, 5], amount = 11,既然我要凑11块钱,首先我可以选择面额为1, 2, 5是三种硬币,那么如果我
>对金额11凑硬币数

  • 金额:11
选择面额 剩余金额 硬币数
1 10 1
2 9 1
5 6 1

>对金额10,9,6分别继续凑硬币数

  • 金额:10
选择面额 剩余金额 硬币数
1 9 2
2 8 2
5 5 2
  • 金额:9
选择面额 剩余金额 硬币数
1 8 2
2 7 2
5 4 2
  • 金额:6
选择面额 剩余金额 硬币数
1 5 2
2 4 2
5 1 2

>对金额9,8,5分别继续凑硬币数
>对金额8,7,4分别继续凑硬币数
>对金额5,4,1分别继续凑硬币数

直到等于金额,或者发现无法凑齐整数的金额,则结束。
这是自上而下的分析思路,然后从分析过程也发现,很多金额会呗计算多遍,如果9,8,5等等,为了避免不必要的回溯,提高效率,使用空间换时间的方式,使用备忘录法,自下而上计算前面金额所需要的硬币数,然后再使用计算好的金额去计算大金额所需要的硬币数,像这题,我们可以先计算金额为1,2,3,4,10分别所需要的最小硬币数,那么不就直接可以统计出金额为11所需要的最小硬币数了吗?

3. 解决思路

状态dp[value],表示金额为value时,所需要的最小硬币数。那么它会等于dp[value-coins[j]]+1(0=<j<=n)
状态转移方程:dp[value] = Math.min(dp[value], dp[value-coins[j]]+1);

4. 代码实现(java)

package com.algorithm.leetcode.dynamicAllocation;/*** Created by 凌 on 2018/12/15.* 描述:322. Coin Change*/
public class CoinChange {public static void main(String[] args) {
//        int[] coins = {1, 2, 5};
//        int amount = 11;int[] coins = {2};int amount = 0;int result = coinChange(coins,amount);System.out.println(result);}public static int coinChange(int[] coins, int amount) {if (coins == null || coins.length==0 ){return -1;}//f(n) = min(f(n) , f(n - coins[i])+1 )  ,//dp[i]=j表示组成i元,最少需要j个硬币int[] dp = new int[amount+1];//组成1元,2元,,,n元需要的最小硬币数for (int value = 1; value <= amount; value++) {//这里必须设置为Integer.MAX_VALUE-1,而不是Integer.MAX_VALUE,因为后面有dp[i - coins[j]] + 1的操作,// 如果为MAX_VALUE,+1则为负数最小值dp[value] = Integer.MAX_VALUE -1;//遍历所有价值的硬币,找到符合组合的硬币for (int j = 0; j < coins.length; j++) {if (value >= coins[j]){dp[value] = Math.min(dp[value], dp[value-coins[j]]+1);}}}return dp[amount] == Integer.MAX_VALUE-1 ? -1 : dp[amount];}
}

5. 拓展,求最大硬币数
分析方法同求最小硬币数。

状态dp[value],表示金额为value时,所需要的最大硬币数。那么它会等于dp[value-coins[j]]+1(0=<j<=n)
状态转移方程:dp[value] = Math.max(dp[value], dp[value-coins[j]]+1);

/*** 求最大硬币数* @param coins* @param amount* @return*/public static int moreCoins(int[]coins,int amount){if (coins==null || coins.length==0 || amount<0){return -1;}//必须注意amount == 0这种特殊情况,因为最后dp[amount] == 0 是直接返回-1,所以需要提前特殊处理if (amount == 0){return 0;}//dp[i]=j表示组成i元,最多需要j个硬币int[] dp=new int[amount+1];for (int i = 1; i <= amount; i++) {
//            dp[i]=Integer.MIN_VALUE+1;for (int j = 0; j < coins.length; ++j) {if (coins[j] <= i) {dp[i] = Math.max(dp[i], dp[i - coins[j]] + 1);}}}return dp[amount] == 0 ? -1 : dp[amount];}
```

322. Coin Change相关推荐

  1. leetcode 322. Coin Change | 322. 零钱兑换(动态规划)

    题目 https://leetcode.com/problems/coin-change/ 题解 也许是第一次在没看答案的情况下写的动态规划- 第一反应是,这题不是广义背包吗?想了一下,不是,因为广义 ...

  2. LeetCode 322. Coin Change

    原题 You are given coins of different denominations and a total amount of money amount. Write a functi ...

  3. 动态规划 Leetcode 322 Coin Change(零钱兑换)

    题目 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 链接(中文版):https: ...

  4. leetcode 322. Coin Change-硬币交换|动态规划

    原题链接:322. Coin Change [思路-Java] 本题考查动态规划.也许一开始很容易想到用贪心算法,但是贪心算法在某些情况下是不成立的,比如coins = [1, 3, 5, 6],要a ...

  5. LeetCode 518 Coin Change 2 (python)

    目录 LeetCode 518 Coin Change 2 (python) Code 欢迎一起来参与leetcode刷题项目 LeetCode 518 Coin Change 2 (python) ...

  6. Lightoj 1231 - Coin Change (I) (裸裸的多重背包)

    题目链接: Lightoj  1231 - Coin Change (I) 题目描述: 就是有n种硬币,每种硬币有两个属性(价值,数目).问用给定的硬币组成K面值,有多少种方案? 解题思路: 赤果果的 ...

  7. C++coin change 硬币找零(附完整源码)

    coin change 硬币找零 coin change 硬币找零算法的完整源码(定义,实现,main函数测试) coin change 硬币找零算法的完整源码(定义,实现,main函数测试) #in ...

  8. 利用动态规划(DP)解决 Coin Change 问题

    问题来源 这是Hackerrank上的一个比较有意思的问题,详见下面的链接: https://www.hackerrank.com/challenges/ctci-coin-change 问题简述 给 ...

  9. hdu2069(Coin Change)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2069 Coin Change Time Limit: 1000/1000 MS (Java/Other ...

  10. Coin Change【硬币找零】

    一.题目 英文:Coin Change 中文:硬币找零 二.内容要求 英文:You are given coins of different denominations and a total amo ...

最新文章

  1. Uchome的登录验证机制
  2. IIs+php 最精简的环境配置
  3. 计算机连接拒绝访问,Win10系统下Windows无法连接到打印机,拒绝访问的解决办法...
  4. 使用https协议解决掉顽固不化的已解密的登录请求
  5. 基于Flask框架的Python web程序的开发实战 二 项目组织结构
  6. hnu暑期实训之487-3279 字符串处理
  7. mysql 索引失效的情况
  8. git卡在Resolving deltas 100%的解决办法
  9. 什么样的对象会被直接放入老年代
  10. [LeetCode] Decode Ways [33]
  11. Spring bean的作用域有哪些?
  12. Stripies POJ 1862
  13. 广告的术语和简称大全
  14. g4560和二代i5_两款处理器奔腾G4560和i5-7400差距?
  15. 三个和尚没水喝的启发
  16. spring框架中的单例Beans是线程安全的么?
  17. re-complie_re-中文_
  18. css flex布局 —— 容器属性 flex-wrap
  19. 分享一些手机的测试点
  20. 国家计算机网络工程师考试,计算机四级网络工程师考试内容了解一下!

热门文章

  1. 中学生读《皮囊》有感相关体会4300字[图]
  2. 存储容量及相关计算单位
  3. 【C语言进阶】预定义详解
  4. 买火车票的过来看看,提供一个小工具,不一定能买到票,但是可以实现自动登录,自动刷票,自动重新提交订单!...
  5. 读书文摘卡 -《大秦帝国》
  6. 2010 我的求职经历(2)
  7. oracle hugepage设置,Linux系统下快速配置HugePages的完整步骤
  8. 记录每日习题(35)
  9. 『.NET Core CLI工具文档』dotnet-publish
  10. 笔记本装双系统!win10+Linux!所有的坑自己一个个爬过来,纪念一下。