动态规划——零钱兑换(Leetcode 322)
题目选自Leetcode 322.零钱兑换
想必大家看一眼就明白了(bushi),这就是动态规划的背包问题~
算法思想
那么,既然知道了这是个动态规划问题,就要思考如何列出正确的状态转移方程?
1、确定 base case,这个很简单,显然目标金额
amount
为 0 时算法返回 0,因为不需要任何硬币就已经凑出目标金额了。2、确定「状态」,也就是原问题和子问题中会变化的变量。由于硬币数量无限,硬币的面额也是题目给定的,只有目标金额会不断地向 base case 靠近,所以唯一的「状态」就是目标金额
amount
。3、确定「选择」,也就是导致「状态」产生变化的行为。目标金额为什么变化呢,因为你在选择硬币,你每选择一枚硬币,就相当于减少了目标金额。所以说所有硬币的面值,就是你的「选择」。
4、明确
dp
函数/数组的定义。我们这里讲的是自顶向下的解法,所以会有一个递归的dp
函数,一般来说函数的参数就是状态转移中会变化的量,也就是上面说到的「状态」;函数的返回值就是题目要求我们计算的量。就本题来说,状态只有一个,即「目标金额」,题目要求我们计算凑出目标金额所需的最少硬币数量。所以我们可以这样定义dp
函数:
dp(n)
的定义:输入一个目标金额n
,返回凑出目标金额n
的最少硬币数量。搞清楚上面这几个关键点,解法的伪码就可以写出来了:
// 伪码框架 int coinChange(int[] coins, int amount) {// 题目要求的最终结果是 dp(amount)return dp(coins, amount) }// 定义:要凑出金额 n,至少要 dp(coins, n) 个硬币 int dp(int[] coins, int n) {// 做选择,选择需要硬币最少的那个结果for (int coin : coins) {res = min(res, 1 + dp(n - coin))}return res }
dp
数组的定义:当目标金额为i
时,至少需要dp[i]
枚硬币凑出。PS:为啥
dp
数组初始化为amount + 1
呢,因为凑成amount
金额的硬币数最多只可能等于amount
(全用 1 元面值的硬币),所以初始化为amount + 1
就相当于初始化为正无穷,便于后续取最小值。为啥不直接初始化为 int 型的最大值Integer.MAX_VALUE
呢?因为后面有dp[i - coin] + 1
,这就会导致整型溢出。状态转移方程
解题代码:C++
class Solution {
public:int coinChange(vector<int>& coins, int amount) {int Max = amount + 1;vector<int> dp(amount + 1, Max);dp[0] = 0;for (int i = 1; i <= amount; ++i) {for (int j = 0; j < (int)coins.size(); ++j) {if (coins[j] <= i) {dp[i] = min(dp[i], dp[i - coins[j]] + 1);}}}return dp[amount] > amount ? -1 : dp[amount];}
};
动态规划——零钱兑换(Leetcode 322)相关推荐
- 【算法题目】DFS BFS 动态规划 零钱兑换 Python
322. 零钱兑换 给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amount ,表示总金额.计算并返回可以凑成总金额所需的 最少的硬币个数 .如果没有任何一种硬币组合能组成总金额 ...
- 动态规划——零钱兑换问题
零钱兑换问题 I 1.题目:力扣原题 2.分析 (1)结合我们之前分析的(动态规划解决背包问题),这里硬币有无限个对应完全背包问题.但又存在一点区别:纯完全背包是能否凑成总的金额,本题是要求凑成总金额 ...
- python换零钱_python动态规划-零钱兑换
零钱兑换 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数. 如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: c ...
- 背包型动态规划——零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 你可以认为每种硬币的数量是无限的. ...
- Java零钱兑换leetcode
给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amount ,表示总金额. 计算并返回可以凑成总金额所需的 最少的硬币个数 .如果没有任何一种硬币组合能组成总金额,返回 -1 . ...
- LeetCode刷题复盘笔记—一文搞懂完全背包之322. 零钱兑换问题(动态规划系列第十四篇)
今日主要总结一下动态规划完全背包的一道题目,322. 零钱兑换 题目:322. 零钱兑换 Leetcode题目地址 题目描述: 给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amo ...
- 刷题第45, 46天 | 70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数、139.单词拆分
70. Climbing Stairs 题目链接:70. Climbing Stairs 思路链接:代码随想录动态规划-爬楼梯(进阶) 思路 思路 Code class Solution {publi ...
- 从《零钱兑换》开始的《背包问题》
1. 零钱兑换 Leetcode里有这样一个问题,LeetCode322. 零钱兑换: "给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amount ,表示总金额.计算并 ...
- 【必备算法】动态规划:LeetCode题(六)322. 零钱兑换,518. 零钱兑换 II
322. 零钱兑换² 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: ...
最新文章
- 010_SpringBoot视图层技术thymeleaf-变量输出与字符串操作
- 标题要在3~5字之间-三年总结
- spec文件中的 %pre %post %preun %postun
- profile matlab,使用profile功能对Matlab性能调优
- ipad Simulator 的home 键的调用
- Spring Boot Questions- Part 1
- 快速突破面试算法(内含从简到难的高频题型目录及每题的详解,已经归类整理好并外带博主的免费答疑)
- 【ARM汇编】ARM 指令集和Thumb 指令集
- UEG/A-2H2D单稳态中间继电器
- 夏令营501-511NOIP训练18
- 传奇服务端如何添加地图
- 支付订单中未付款倒计时
- 卷积神经网络(2)--卷积神经网络的认识、黑白图像的卷积操作
- VMMECH007_Thermal Stress in a Bar with Temperature Dependent Conductivity
- luoguP5055 【模板】可持久化文艺平衡树 可持久化非旋转treap
- case class 和 class的区别
- 【java】java中输出字符串中的单个字符及获得其长度
- 网络记账软件测试面试,超级账本test-network测试工作流程
- 【Android】App首页上下滚动快报控件 通知控件 类似京东快报控件(一)
- Python,OpenCV中的光学字符识别OCR文章汇总