你有三种硬币,分别面值2元,5元和7元,每种硬币都有足够多。买一本书需要27元。如何用最少的硬币组合正好付清,不需要对方找钱?

这道题是lintcode编号669的Coin Change问题。

实现方式有两个钟,一种是自底向上推导方法,另一种是自顶向下推导。

自底向上:

package leecode.daynamicprogramming;public class CoinChange {public static void main(String[] args) {int[] a = {2,5,7};int ret = coinChange(a, 9);System.out.println(ret);}public static int coinChange(int[] A, int M) {/** 原理:* 1. 求一个给定值的最小数量硬币组合,可以将问题拆分成如下**   A = [2,5,7]  // M = 27*   f[X] = min{f[X-2]+1, f[X-5]+1, f[X-7]+1}*  他利用的原理是假设获得总额的组合,最后一个硬币币值是n, 总额是m, 那最小硬币数量一定是f(m) = f(m-n) + 1;* 我们将最后一个硬币的币值全部枚举一遍,比如币值有2,5,7三种情况,总额27,这样我们可以获取三种可能,从中选一个最小值,就是我们要的* 结果。* 已给出示例为例,几种特殊情况:* f(0)总是等于0* f(1)无法得到货币组合,我们给出值是无穷大(程序中用Integer.MAX_VALUE代表)* f(2)=1* f(3)业务无法得到组合,所以也是无穷大* 以此类推* *///f(x)代表给定硬币总额为x,求总和为x的最小硬币组合(硬币数量最少),这里用一个数组f代表。// 每一个数组下标表示每一种总额, 对应的数组的值表示对应的组成该数额的硬币数量。int[] f = new int[M + 1];//边界条件: 总额为0,需要硬币的数量为0,所以f[0]=0。如果总额无论怎么用给定货币组合,都达不到,则f(x)=Integer.MAX_VALUEf[0] = 0;int n = A.length;// 硬币的种类// 初始化, 0个硬币  f[0] = 0;// f[1], f[2], ... , f[27] = Integer.MAX_VALUE//这里可以不显示指定f[0] = 0, jvm默认会给整形数组初始化为0for (int i = 1; i <= M; i++) {f[i] = Integer.MAX_VALUE;}for (int i = 1; i <= M; i++) {// 使用第j个硬币 A[j]    // f[i] = min{f[i-A[0]]+1, ... , f[i-A[n-1]]+1}//从低到高,逐一计算f(x)的值,后边的值会利用前边算出的值。for (int j = 0; j < n; ++j) {// 如果通过放这个硬币能够达到重量i/*f[i - A[j]] = Integer.MAX_VALUE表示最后一枚硬币是A[j],且总额减去该枚硬币的值,可能的硬币数量组合是.MAX_VALUE* 的情况,也即总额减掉最后一枚币值A[j],用任何货币组合都无法实现,这种情况就没必要再更改f[i]的值了*/if (i >= A[j] && f[i - A[j]] != Integer.MAX_VALUE) {//在遍历每一个硬币的时候,f(i)可能会变化,总是获取当前f(i)和f(i-A[j])+1中最小的哪一个当作最新的f(i)的值f[i] = Math.min(f[i - A[j]] + 1, f[i]);}}}if (f[M] == Integer.MAX_VALUE) {return -1;}return f[M];}
}

自底向上另一种写法:

public class Solution {public int coinChange(int[] coins, int amount) {int max = amount + 1;int[] dp = new int[amount + 1];Arrays.fill(dp, max);dp[0] = 0;for (int i = 1; i <= amount; i++) {for (int j = 0; j < coins.length; j++) {if (coins[j] <= i) {dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);}}}return dp[amount] > amount ? -1 : dp[amount];}
}

自顶向下:


public class Solution {public int coinChange(int[] coins, int amount) {if (amount < 1) {return 0;}return coinChange(coins, amount, new int[amount]);}private int coinChange(int[] coins, int rem, int[] count) {if (rem < 0) {return -1;}if (rem == 0) {return 0;}if (count[rem - 1] != 0) {return count[rem - 1];}int min = Integer.MAX_VALUE;for (int coin : coins) {int res = coinChange(coins, rem - coin, count);if (res >= 0 && res < min) {min = 1 + res;}}count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;return count[rem - 1];}
}

动态规划算法计算硬币组合相关推荐

  1. 算法题 硬币组合问题

    原文:http://www.cnblogs.com/python27/archive/2013/09/05/3303721.html 问题描述 假设我们有8种不同面值的硬币{1,2,5,10,20,5 ...

  2. hdu 2069 动态规划_所有硬币组合

    文章目录 前言 一.题目 二.解决一波 1.不完全解决方案分析 2.不完全解决方案代码 3.完全解决方案分析 4.完全解决方案代码 前言 又双叒是一道硬币问题,别问,问就是硬币,安排一波~ 一.题目 ...

  3. 用动态规划算法求解最少硬币问题 c语言,动态规划算法求解硬币找零问题

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 看着这代码怎么这么熟悉. package 动态规划找零; import java.util.Scanner; public class Main { pu ...

  4. 矩阵相乘的strassen算法_矩阵乘法的Strassen算法+动态规划算法(矩阵链相乘和硬币问题)...

    矩阵乘法的Strassen 这个算法就是在矩阵乘法中采用分治法,能够有效的提高算法的效率. 先来看看咱们在高等代数中学的普通矩阵的乘法 两个矩阵相乘 上边这种普通求解方法的复杂度为: O(n3) 也称 ...

  5. Python数据结构20:动态规划:找零兑换问题的动态规划解法并显示使用的硬币组合

    在我们使用递归算法时,可能会出现规模庞大的重复计算,用一个中间表记录每个计算过的最优解法,就可以避免大量的重复计算.中间结果记录可以很好解决找零兑换问题.实际上,这种方法还不能称为动态规划,而是叫做& ...

  6. 硬币拼凑指定面额的动态规划算法

    拼凑钱币 题目来源:美团点评2017秋招笔试题 题目描述: 给你六种面额1.5.10.20.50.100元的纸币,假设每种币值的数量都足够多,编写程序求组成N员(N为0-10000的非负整数)的不同组 ...

  7. 动态规划之硬币组合问题

    问题:如果我们有面值为1元.3元和5元的硬币若干枚,如何用最少的硬币凑够11元? 动态规划的本质是将原问题分解为同性质的若干相同子结构,在求解最优值的过程中将子结构的最优值记录到一个表中以避免有时会有 ...

  8. 硬币组合问题python_动态规划之硬币组合问题

    问题:如果我们有面值为1元.3元和5元的硬币若干枚,如何用最少的硬币凑够11元? 动态规划的本质是将原问题分解为同性质的若干相同子结构,在求解最优值的过程中将子结构的最优值记录到一个表中以避免有时会有 ...

  9. JavaScript实现动态规划方法计算特定位置的斐波那契数fibonacciNth算法(附完整源码)

    JavaScript实现动态规划方法计算特定位置的斐波那契数fibonacciNth算法(附完整源码) fibonacciNth.js完整源代码 fibonacciNth.js完整源代码 export ...

最新文章

  1. 四层和七层交换技术-loadbalance
  2. 配置Xmanager连接linux
  3. 用wget循环获取指定url下的文件
  4. java中JTextPane使输出字符到指定的宽度换行,并将垂直滚动条的位置移动到输出的最后位置...
  5. 我们工作到底为了什么(这篇文章很重要)----强烈推荐
  6. 【转】PHP的异常处理类Exception的使用及说明
  7. linux 编译 freescale arm 的gdb server
  8. arduino机器人设计与制作_百元搭建人工智能自主导航机器人
  9. mysql数据库管理命令_MySQL数据库管理基本命令
  10. 钢材规格解读的软件_东洲废旧机械设备回收整厂拆除详细解读
  11. 100行代码实现最简单的基于FFMPEG+SDL的视频播放器
  12. [19/06/08-星期六] CSS基础_表格表单
  13. GDB中打印pthread_internal_t的方法
  14. C语言中文件指针,文件位置指针,详细解析
  15. 提高迅雷下载速度 超好用,下载速度实实在在的提高了!
  16. WordPress社交问答社区主题
  17. 华为p20支持手机云闪付吗_华为哪些手机支持云闪付
  18. 超声检查腕骨间关节有助于最大程度地发现RA腕骨间滑膜炎
  19. 短视频查重机制及去重方法
  20. HTTP keep-alive和TCP keepalive的区别,你了解吗?

热门文章

  1. 使用腾讯JS-SDK实现汽车沿轨迹行驶
  2. 后台管理系统2——登录、退出、注册功能、个人中心页面
  3. CB官方推荐AP英语文学与写作必读书目,2023报名中
  4. 供水管网压力如何进行精细化管理?
  5. goldengate ddl mysql_Oracle GoldenGate 12.2-异构环境的单项复制(支持DDL复制)
  6. 「硬见小百科」工程师离不开的那些电路设计工具
  7. wxid加好友 wxid转微信号
  8. 哪位明星会是你心目中的“旗袍”代言人?
  9. EXCEL 合并成绩表格及格式转换
  10. serializeArray 与 serialize