[杨小白]_leetcode_322. 零钱兑换

72 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标300题,记录从0到1的全过程!!

322. 零钱兑换

322. 零钱兑换

这是一道中等难度的题,首先我拿到这个题的时候,第一反应是,这么简单还算得上中等难度?后来发现我把题目理解错了。

题目

给你一个整数数组 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[1,5,8],目标amount是10。如果按照我最开始的算法,首先是拿8,然后还剩2,再拿两个1即可,所有最后拿的就是[8,1,1]返回值为3。

但是这个题要找到最小的数量那就是[5,5]结果为2是最小的。所以大家千万别陷入这个思维误区哦~

类似基础题

这里我又要引入几个算法思想和这个题同出一源的题目了,大家可以移步先吃透这几个题哦,这样对于这道题肯定会更容易看懂了。

[杨小白]_java_leetcode 509.斐波那契数

[杨小白]_java_leetcode 70.爬楼梯

[杨小白]_java_leetcode 746. 使用最小花费爬楼梯

[杨小白]_java_leetcode 62. 不同路径

用一个记忆数组db记录i元需要的最少coins数量,然后对于后续的i,他等于db中i分别减去coins数组的元素后,最小的一个+1,直到amount,这样得到的数就是最小的。

类比于爬楼梯,每次可以爬1,3,6阶,对于7阶台阶就需要db[6]+1或者db[4]+1或者db[1]+1,那边给db[7]的赋值就是这三个中的最小值。以此内推一直到需要求到的amount即可。

2.解法

class Solution {
    public int coinChange(int[] coins, int amount) {
        if (amount==0) return 0;
        Arrays.sort(coins);
        int[] db = new int[amount + 1];
        Arrays.fill(db, Integer.MAX_VALUE);
        db[0] = 0;
        for(int coin: coins) {
            for(int i = coin; i <=amount; i++) {
                if (db[i - coin] != Integer.MAX_VALUE) {
                    db[i] = Math.min(db[i - coin] + 1, db[i]);
                }
            }
        }

        return db[amount] == Integer.MAX_VALUE ? -1 : db[amount];
    }
}

提交排名

image.png

3.结束

这个题的思想是很常见的,但是还是由很多细节需要注意,gogogo,刷题刷题,每天一道,三年1000道!!!!