零钱兑换问题

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

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

示例 2: 输入: coins = [2], amount = 3
输出: -1

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

题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change

解题思路:
如果你会爬楼梯问题,此题便会变得很容易理解了,
例如:
n阶楼梯,每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
此题链接在LeetCode的70题
https://leetcode-cn.com/problems/climbing-stairs/

那我们就可以把此题理解成,amount阶楼梯,每次你可以爬coins数组每个值对应个台阶,哪种方法爬的次数最少?也就是在不同方法中选取出攀爬最少的

此时列出dp状态转移方程:

状态dp[i]            i表示台阶              dp[i]表示次数

dp方程:
dp[i]=min{dp[i-coins[j] + 1}      0<j<coins.size     i > coins[j]

最后c++实现:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

int coinChange(vector<int>& coins, int amount)
{
    int maxn = amount + 1;
    vector<int> dp(amount+1,maxn);   //定义数组的大小及初始化

    dp[0] = 0;    //无面值为0的硬币,所以dp[0]=0
    for(int i = 1; i <= amount; i++) {       //每一阶楼梯对应的方法数
       for(int j = 0; j < coins.size(); j++)  
        {
            if(coins[j] <= i) {
                dp[i] = min(dp[i],dp[i-coins[j]]+1);   //较小次数
            }
        }
    }

    if(dp[amount] > amount)
        return -1;
    else
        return dp[amount];
}

int main()
{
    vector<int> coins;
    coins.push_back(1);
    coins.push_back(2);
    coins.push_back(5);
    int num = 11;
    cout << coinChange(coins,num) << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值