写点什么

每日一题:LeetCode-322. 零钱兑换

作者:半亩房顶
  • 2023-12-05
    北京
  • 本文字数:1471 字

    阅读完需:约 5 分钟

每日一题:LeetCode-322. 零钱兑换

刷题使我快乐,满脸开心.jpg


题目

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。


计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1


你可以认为每种硬币的数量是无限的。


示例 1:


输入:coins = [1, 2, 5], amount = 11输出:3 解释:11 = 5 + 5 + 1
复制代码


示例 2:


输入:coins = [2], amount = 3输出:-1
复制代码


示例 3:


输入:coins = [1], amount = 0输出:0
复制代码


提示:


  • 1 <= coins.length <= 12

  • 1 <= coins[i] <= 231 - 1

  • 0 <= amount <= 104

思路

最开始看到题目,直接就开始呼贪心代码,然后写完之后,发现会超时(后来看题解时候,发现开始还是有贪心剪枝可以过的,后来更新了用例就不得行了...)


那就换思路!然后就想到了这个感觉很像爬楼梯,类比下就是:

我们每一次只能爬coins中给定数字个台阶,直到爬到指定的台阶数,然后求得最少爬台阶次数。


那顺着这个思路,就上动态规划吧:


  • dp[i] 表示 amount 为 i` 时,最少爬台阶次数

  • 初始条件为dp[0] = 0


剩下就没啥要说的了,上代码,有个剪枝细节在备注里了~

代码

动态规划

func coinChange(coins []int, amount int) int {    if len(coins) <= 0 {        return -1    }    if amount == 0 {        return 0    }
sort.Slice(coins, func(i, j int) bool { return coins[i] < coins[j] })
max := amount + 1 dp := make([]int, amount+1) for i := 1; i <= amount; i++ { dp[i] = max } for nowAmount := 1; nowAmount <= amount; nowAmount++ { for i := 0; i < len(coins); i++ { // 因为有了排序,所以一旦开始面值大于当前所求总和 // 后面的面值就不需要尝试了 if coins[i] > nowAmount { break } if dp[nowAmount-coins[i]]+1 < dp[nowAmount] { dp[nowAmount] = dp[nowAmount-coins[i]] + 1 } } } if dp[amount] == max { return -1 } return dp[amount]}
复制代码

贪心

func coinChange(coins []int, amount int) int {    if len(coins) <= 0 {        return -1    }    if amount == 0 {        return 0    }
sort.Slice(coins, func(i, j int) bool { return coins[i] > coins[j] })
res := amount + 1 var getNum func(coins []int, nowNum, remainRes int) getNum = func(coins []int, nowNum, remainRes int) { for i := 0; i < len(coins); i++ { if coins[i] == remainRes && nowNum+1 < res { res = nowNum + 1 } else if remainRes > coins[i] { // 第二个剪枝,假设都用当前币种,所需数量依然大于现有结果, // 那么就直接放弃,肯定结果数更大 if remainRes/coins[i] > res-nowNum { break } getNum(coins, nowNum+1, remainRes-coins[i]) } // 第一个剪枝,对于超出结果的面值放弃,找更小面值硬币 } } getNum(coins, 0, amount)
if res == amount+1 { return -1 } return res}
复制代码



欢迎关注公众号查看更多题目~


发布于: 刚刚阅读数: 6
用户头像

半亩房顶

关注

人生那么长,能写多少bug? 2018-11-16 加入

我希望,自己永远是自己。我希望,远离bug。

评论

发布
暂无评论
每日一题:LeetCode-322. 零钱兑换_面试_半亩房顶_InfoQ写作社区