力扣322关于零钱兑换问题

文章介绍了如何通过动态规划解决LeetCode中的零钱兑换问题,通过确定状态、转移方程和边界条件,计算最少硬币组合来凑成给定金额。代码示例展示了如何实现这一算法。
摘要由CSDN通过智能技术生成

力扣322关于零钱兑换问题

问题描述

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1

思路分析

1、确定状态
简单的说,就是解动态规划时需要开一个数组,数组的每个元素f[i]或者f[i][j]代表什么,类似解数学题中,xyz代表什么一样,具体分为下面两个步骤:
-------研究最优策略的最后一步
-------化为子问题
2、转移方程
根据子问题定义直接得到
3、初始条件和边界情况
初始条件一般都是a[0]、a[1]这种,多看看
边界条件主要是看数组的边界,数组越不越界
4、计算顺序
利用之前的计算结果
详细过程:
1、确定状态
虽然我们不知道最优策略是什么,但是最优策略一定是k枚硬币a1,a2…ak加起来等于11
所以一定有一枚最后的硬币:ak
除掉这枚硬币,前面硬币的面值相加起来是11-ak,所以就将原问题转化为了子问题:
原问题:最少用多少枚硬币拼出11(k枚)
子问题:最少用多少枚硬币拼出11-ak(k-1枚)
经过这两歩,得出状态:f[X]=最少用多少枚硬币拼出X
2、转移方程
设状态f[X]=最少用多少枚硬币拼出X
转移方程如下
f[x]=min{f[x-1]+1,f[x-2]+1,f[x-5]+1}
其中f[x]为拼出x最少需要的硬币数,f[x-1]+1为拼出x-1最少的硬币数,再加上最后一枚硬币1,以此类推。
3、初始条件和边界情况
边界条件x-1,x-2,x-5,小于0时,应该进行处理,这种情况其实就是拼不出来的情况,定义为正无穷初始条件一般就是根据转移方程计算不出来的值,从转移方程变量为0或1来选,根据题目进行分析,这个题目的初始条件就是f[0]=1,代入公式的话应该f[0]为正无穷,显然错误,所以自己定义f[0]=0,保证每次计算f[x]时用到的f[x-1],f[x-2]等都是已经计算过的。
4、计算顺序
这个题目应该是正序的,当我们计算到f[x]时,f[x-1],f[x-2],f[x-5]都已经得到结果了
总结:
每一次尝试三种硬币,一共11步;
与递归算法相比,没有任何重复计算;
算法时间复杂度(需要进行的步数):11* 3(amount * coinsSize)

代码示例

int min_fun(int a, int b)
{
        int c = a<b?a:b;
        return c;
}
int coinChange(int* coins, int coinsSize, int amount){
    //1、确定状态
    int f[amount+1];
    //初始化
     f[0] = 0;
    
    //计算顺序 从小到大 i表示需要凑的总数
    for(int i = 1;i<=amount;i++)
    {
        f[i] = INT_MAX;
        for(int j = 0;j<coinsSize;j++)
        {
            //3.边界情况 f[i-coins[j]]!=INT_MAX 表示凑不出硬币时,而且INT_MAX相加可能还会溢出
            if(i>=coins[j] && f[i-coins[j]]!=INT_MAX)
            {
                //2、转移方程
                f[i] = min_fun(f[i],f[i-coins[j]]+1);
            }
        }
    }
    //当凑不出时,f[amount]仍然为INT_MAX,我们需要赋值为-1,最后返回f[amount]
    if(f[amount] == INT_MAX)
        f[amount] = -1;

        return f[amount];

}

官网链接

力扣链接: https://leetcode.cn/

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值