题目选自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)相关推荐

  1. 【算法题目】DFS BFS 动态规划 零钱兑换 Python

    322. 零钱兑换 给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amount ,表示总金额.计算并返回可以凑成总金额所需的 最少的硬币个数 .如果没有任何一种硬币组合能组成总金额 ...

  2. 动态规划——零钱兑换问题

    零钱兑换问题 I 1.题目:力扣原题 2.分析 (1)结合我们之前分析的(动态规划解决背包问题),这里硬币有无限个对应完全背包问题.但又存在一点区别:纯完全背包是能否凑成总的金额,本题是要求凑成总金额 ...

  3. python换零钱_python动态规划-零钱兑换

    零钱兑换 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数. 如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: c ...

  4. 背包型动态规划——零钱兑换

    给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 你可以认为每种硬币的数量是无限的. ...

  5. Java零钱兑换leetcode

    给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amount ,表示总金额. 计算并返回可以凑成总金额所需的 最少的硬币个数 .如果没有任何一种硬币组合能组成总金额,返回 -1 . ...

  6. LeetCode刷题复盘笔记—一文搞懂完全背包之322. 零钱兑换问题(动态规划系列第十四篇)

    今日主要总结一下动态规划完全背包的一道题目,322. 零钱兑换 题目:322. 零钱兑换 Leetcode题目地址 题目描述: 给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amo ...

  7. 刷题第45, 46天 | 70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数、139.单词拆分

    70. Climbing Stairs 题目链接:70. Climbing Stairs 思路链接:代码随想录动态规划-爬楼梯(进阶) 思路 思路 Code class Solution {publi ...

  8. 从《零钱兑换》开始的《背包问题》

    1. 零钱兑换 Leetcode里有这样一个问题,LeetCode322. 零钱兑换: "给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amount ,表示总金额.计算并 ...

  9. 【必备算法】动态规划:LeetCode题(六)322. 零钱兑换,518. 零钱兑换 II

    322. 零钱兑换² 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: ...

最新文章

  1. 010_SpringBoot视图层技术thymeleaf-变量输出与字符串操作
  2. 标题要在3~5字之间-三年总结
  3. spec文件中的 %pre %post %preun %postun
  4. profile matlab,使用profile功能对Matlab性能调优
  5. ipad Simulator 的home 键的调用
  6. Spring Boot Questions- Part 1
  7. 快速突破面试算法(内含从简到难的高频题型目录及每题的详解,已经归类整理好并外带博主的免费答疑)
  8. 【ARM汇编】ARM 指令集和Thumb 指令集
  9. UEG/A-2H2D单稳态中间继电器
  10. 夏令营501-511NOIP训练18
  11. 传奇服务端如何添加地图
  12. 支付订单中未付款倒计时
  13. 卷积神经网络(2)--卷积神经网络的认识、黑白图像的卷积操作
  14. VMMECH007_Thermal Stress in a Bar with Temperature Dependent Conductivity
  15. luoguP5055 【模板】可持久化文艺平衡树 可持久化非旋转treap
  16. case class 和 class的区别
  17. 【java】java中输出字符串中的单个字符及获得其长度
  18. 网络记账软件测试面试,超级账本test-network测试工作流程
  19. 【Android】App首页上下滚动快报控件 通知控件 类似京东快报控件(一)
  20. Python,OpenCV中的光学字符识别OCR文章汇总

热门文章

  1. windows WEB 服务器安全策略
  2. linux基础(十一)--系统初始化的简谈
  3. Zend Framework实例教程三
  4. 开源代码 不开源_提供开源代码反馈的4个最佳实践
  5. 我妈妈要求一台Linux计算机
  6. (1)Uni-App入门
  7. VSCode自定义代码片段9——JS中的面向对象编程
  8. MyBatis 解析运行原理
  9. HTML5 Web Storage API
  10. Ubuntu自带简易录屏工具