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

说明:你可以认为每种硬币的数量是无限的。
链接:https://leetcode-cn.com/problems/coin-change

解题思考:

硬币问题可以用数学表述成如下形式:

在不断的迭代dp()中,当出现n-coin==0时,兑换零钱加一次。

从递归的迭代过程思考,可以画出迭代树表示,例如假设amount=9,coins={1,2,5}

图中相同颜色的色块是在迭代过程中重复计算的部分。

方法1:递归

递归算法的时间复杂度分析:子问题总数 x 每个子问题的时间

子问题总数为递归树节点个数,这个比较难看出来,是 O(n^k),总之是指数级别的。每个子问题中含有一个 for 循环,复杂度为 O(k)。所以总时间复杂度为 O(k * n^k),指数级别

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:def count(n):# 基本情况的判定if n==0 : return 0if n<1 : return -1# 初始化min_coins=float('INF')for coin in coins:# 子问题的分解subproblem=count(n-coin)if subproblem == -1:continue# min_coins=min(min_coins,1+subproblem)# 如果一直continue,min_coins 不变,就代表没有可以分的可能return min_coins if min_coins !=float('INF') else -1return count(amount)

方法二: 加入记录表的迭代

「记录表」大大减小了子问题数目(即替代了上图中部分同色块的数值计算),完全消除了子问题的冗余,所以子问题总数不会超过金额数 n,即子问题数目为 O(n)。处理一个子问题的时间不变,仍是 O(k),所以总的时间复杂度是 O(kn)。

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:memo={}def count(n):# 查找子问题的值if n in memo:return memo[n]if n==0 : return 0if n<1 : return -1# 初始化min_coins=float('INF')for coin in coins:# 子问题分解subproblem=count(n-coin)if subproblem == -1:continuemin_coins=min(min_coins,1+subproblem)# 存储子问题的解memo[n]= min_coins if min_coins !=float('INF') else -1return memo[n]return count(amount)

方法三:用list代替dict中间表的迭代

采用“由底向上”的方式,从1,2,3。。。开始计算,直到n。

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:# 初始化结果集# 每一个下标对应对应amount,下标对应的最后元素值就是零钱的最小个数res=[float('INF')]*(amount+1)res[0]=0for i in range(amount+1):for coin in coins:# 不可分就下一轮if (i-coin) <0: continue# 对每一个i进行计算res[i]=min(res[i],1+res[i-coin])if res[amount] == float('INF'):return -1else:return res[amount]

方法四:利用整除减少循环次数

每次递归中判断剩余的amount%nums[index]是不是为0,如果是的话,表示当前的coins[index]可以将amount塞满,那么此时就是最优解了,记录下来;如果不是的话,那么我们只需要递归判断需要多少个coins[index]即可。如果遍历到最后一个coins[-1]且无法塞满amount的话,那么无解。

最后还有一个非常重要的剪枝,如果当前硬币coins[index](放满amount)放入后,硬币数比之前的结果都大的话,那么就不用继续判断后面的硬币了(因为硬币是排序过的)。

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:n = len(coins)coins.sort(reverse=True)self.res = float("inf")def dfs(index,target,count):coin = coins[index]if math.ceil(target/coin)+count>=self.res:returnif target%coin==0:self.res = count+target//coinif index==n-1:returnprint([range(target//coin,-1,-1)])for j in range(target//coin,-1,-1):dfs(index+1,target-j*coin,count+j)dfs(0,amount,0)return int(self.res) if self.res!=float("inf") else -1

Python版-LeetCode 学习:322 零钱兑换问题相关推荐

  1. LeetCode:322. 零钱兑换(python)

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

  2. 【LeetCode】322. 零钱兑换 结题报告 (C++)

    原题地址:https://leetcode-cn.com/problems/coin-change/ 题目描述: 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成 ...

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

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

  4. leetcode: 322.零钱兑换

    322.零钱兑换 来源:力扣(LeetCode) 链接: https://leetcode.cn/problems/coin-change/ 给你一个整数数组 coins ,表示不同面额的硬币:以及一 ...

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

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

  6. golang力扣leetcode 322.零钱兑换

    322.零钱兑换 322.零钱兑换 题解 代码 322.零钱兑换 322.零钱兑换 题解 //state: dp[i]金额为i时所需最少硬币个数 //function: dp[i]=dp[i-n]+1 ...

  7. Java实现 LeetCode 322 零钱兑换

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

  8. [LeetCode] 322.零钱兑换 五种方法讲解

    322.零钱兑换 五种方法讲解 文章目录 322.零钱兑换 五种方法讲解 1 问题描述 2 问题分析 3 解决策略 3.1 递归-暴力解决 3.2 递归-加入存储 3.3 BFS 3.4 动态规划-自 ...

  9. LeetCode 322. 零钱兑换

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

最新文章

  1. [转]C#异步编程的实现方式(1)——异步委托
  2. 投资100亿美元,谷歌计划在2020年向美国办事处和数据中心
  3. alias--linux
  4. 在jekyll模板博客中添加网易云模块
  5. 【转】进阶 JavaScript 必知的 33 个点【进阶必备】
  6. 解决CentOS出现“No package redis available“提示问题
  7. Android 基本控件使用
  8. 【C++ Primer】第十五章 友元、异常和其他 --之一---友元和嵌套类
  9. CentOS下MFS分布式文件系统搭建
  10. Digilent提供的PmodOLEDrgb驱动程序
  11. 使用yum update更新文件系统时不更新内核的方法
  12. Python数据的精度
  13. Window下MySQL 8.0重新设置密码
  14. Goolge-TPU论文解读
  15. 无损连接和保持依赖性(有脑就行,尽量说人话版本)
  16. 数字逻辑电路(1)--逻辑代数基础
  17. mp3计算机无法识别,MP3\MP4连接windows电脑后无法识别怎么办
  18. python+win32com分割多页ppt为单页多文件
  19. 崩坏3新版本服务器维护多久,崩坏3V3.5版本10月17日版本更新维护通知
  20. Unity地面拼接实现无限路循环

热门文章

  1. 粗浅地浏览一下,待明日来嘞,认真去刷!
  2. php 获取 所有上级 id,z-blog获取分类以及上级分类的代码
  3. 使用u盘PE系统重装Windows操作系统
  4. C语言打字游戏(无错误警告版)
  5. Word 中添加目录的一般方法
  6. 抖音账号主页设置推荐机制
  7. 风口的猪(小米实习生招聘)
  8. 淘宝滑块的解决方法和api接口
  9. SV中virtual作用
  10. lle算法c++语言,2015年计算机二级C++上机考前冲刺题(4)