硬币找零问题
时间:2022-07-22
本文章向大家介绍硬币找零问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
硬币找零问题是一种经典的背包问题。
顾名思义,就是你去商店买完东西,售货员会给你用若干枚硬币找钱,如何使用这些硬币完成找零。
问题一:组成当前值所需最少的硬币数目
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
该问题的一个简化版,当一个大面值的硬币总是可以由小面值的硬币组合而成时(即参考软妹币),可以使用一种贪心策略即优先使用大面值的直到不能使用再使用小面值的,如此的到的即为最少硬币花费数目。
解决方案
使用完全背包求解。
将不同面额的硬币抽象为成不同的物品,面额为物品的重量,amount为最大容量,每个物品的价值均为一,如此该问题就可以转化为求解恰好装满背包能获得最低的价值问题。
定义dp[i] [j] 为当前可以使用下标为0~i - 1的硬币,组成金额 j 的最小硬币数目。
转移方程如下:
具体推导感兴趣的朋友可以看我以前写的这篇博客:零一背包和完全背包
baseline:
其中把非法状态定义为+无穷。
实现代码如下:
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
for(int i = 1; i <= amount; i++){
dp[i] = Integer.MAX_VALUE;
}
for(int i = 0; i < coins.length; i++){
for(int j = 1; j <= amount; j++){
if(j - coins[i] < 0 || dp[j - coins[i]] == Integer.MAX_VALUE){
continue;
}
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
}
}
return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
}
}
上述为空间压缩之后的代码。
问题二:凑成当前值的组合的数目
给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
示例 1:
输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例 2:
输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额2的硬币不能凑成总金额3。
示例 3:
输入: amount = 10, coins = [10]
输出: 1
注意:
你可以假设:
0 <= amount (总金额) <= 5000
1 <= coin (硬币面额) <= 5000
硬币种类不超过 500 种
结果符合 32 位符号整数
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change-2
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解决方案
还是完全背包。
题目问什么把什么定义dp,定义dp[i] [j]为当前可以使用下标为0~i - 1的硬币,组成金额 j 的方案数目。
转移方程:
由于dp值总是大于0的
baseline:
代码如下:
class Solution {
public int change(int amount, int[] coins) {
int[] dp = new int[amount + 1];
dp[0] = 1;
for(int i = 0; i < coins.length; i++){
for(int j = 1; j < amount + 1; j++){
if(j - coins[i] >= 0){
dp[j] = dp[j] + dp[j - coins[i]];
}
}
}
return dp[amount];
}
}
一点总结:若某个问题可以看成对一些列多个“物品”的组合问题,并且组合时对于“物品”的选择有约束,可以将该问题转化为背包问题求解。
- android Titlebar一行代码实现沉浸式效果
- android自定义状态栏颜色
- android drawable
- PHP伪静态的几种方法
- 蘑菇街Android组件与插件化
- android 之ViewStub
- Xshell利用登录脚本从服务器登录到另外一个服务器
- RecyclerView详解
- Windows平台下安装Eclipse插件,开发Hadoop应用
- Palette状态栏颜色提取,写的不错就分享了
- oracle表空间表分区详解及oracle表分区查询使用方法(转+整理)
- SpannableString 给TextView添加不同的显示样式
- javadoc相关问题
- android混淆和反编译
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java常用设计模式--代理模式(Proxy Pattern)
- 详解爬取搜狐号自媒体的所有文章
- 笑了,面试官问我知不知道异步编程的Future。
- ES6之let和const命令
- [Python] 豆瓣自动回帖、顶帖源码
- 基于OpenMV的人脸识别,支持人脸注册、人脸检测、人脸识别
- FatFs检测并建立多层目录并更改文件名
- Docker安装harbor仓库、更改端口、跨服务器访问
- 字符串处理算法题 -> 替换空格
- 简单二分法查找
- 链表之Python与C
- Python MQTT
- 从键盘输入一个十进制个位数,在屏幕上显示相应数量的该数。 例如,输入3,屏幕上将显示“333”。
- ESP32 OTA详解-中文翻译版
- 汇编语言从键盘输入一个字符串(串长不大于80)以十进制输出字符串中非字母字符的个数(不是a to z或 A to Z)