零钱兑换(Coin Change)java

零钱兑换(Coin Change)java

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangjingao/article/details/82966587

题干

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

示例 1:

输入: coins = [1, 2, 5], amount = 11
输出: 3 
解释: 11 = 5 + 5 + 1
示例 2:

输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。

分析

这题是一道动态规划题。那么我们来找状态转移方程。
来个比较接地气的解释。 首先我们来想一下,我们大脑在遇见这种题的时候是怎么思考的,以示例1举例。coins={1,2,5},当amount=1,2,5时,我们直接就能看到需要一个硬币即可。当amount=6时呢,我们会首先想,
1. 先用硬币面额为1的硬币,然后减去1剩5,那组成5的最少需要多少硬币呢?前面看到了是1,那么就是答案是2;
2. 用面额为2的硬币,然后6-2=4,组成4所需的最少硬币块数是2块(2+2),那么就是3。
3. 用面额为5的硬币,然后6-5=1,组成1所需的最少硬币就是1块,那么答案就是2;

那么转换为程序的话就是首先定义一个数组ans[amount+1],存放amount=i时的最少硬币块数。然后对i=1-amount循环,然后再对硬币面额 j=0-coin.length循环,依次比较用每个硬币面额时的最小硬币块数。
(其实这题不难,解释那么多太详细了,,,,)

代码


    public int coinChange(int[] coins, int amount) {
        //初始化答案数组
        if( amount == 0 ){
            return 0;
        }
        int [] ans = new int[amount+1];
        for( int i = 0 ; i < coins.length ; ++i){
            if( coins[i] > amount ){
                continue;
            }
            ans[coins[i] ] = 1;
        }
        for( int i = 1 ; i <= amount ; ++i ){
            //已经初始化过
            if( ans[i] != 0 ){
                continue;
            }
            //mi用来保存临时最小值
            int mi = Integer.MAX_VALUE;
            for( int j = 0 ; j < coins.length ; ++j ){
                //上一次的面额不合法
                if( i - coins[j] <= 0 || ans[ i - coins[j] ] == 0 ){
                    continue;
                }
                mi = Math.min( mi , ans[i - coins[j]  ] + 1);
            }
           mi = mi == Integer.MAX_VALUE ? 0 : mi ;
           ans[i] = mi;
        }
        return ans[amount] == 0 ? -1 : ans[amount];

    }

运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值