换钱的方法数

题目

给定数组 arr,arr 中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,代表要找的钱数,求换钱有多少种方法。

举例

arr=[5,10,25,1],aim=0.
组成0元的方法有1种,就是所有面值的货币都不用。所以返回1。

arr=[5,10,25,1],aim=15。
组成15元的方法有6种,分别为3张5元、1张10元+1张5元、1张10元+5张1元、10张1元+1张5元、2张5元+5张1元和15张1元。所以返回6。

arr=[3,5],aim=2.
任何方法都无法组成2元。所以返回0。

解答

题目其实可以转化为 aim 由 arr 中的数组成,arr中的数可以重复使用,使用的总次数最少为多少。
这里可以使用动态规划的解法,假设 dp[i] 表示使用arr中数组成i的最少数目,动态规划公式如下所示
dp[i] = min(dp[i - vec[j]]) + 1 ,j >= 0 && j <= arr.size()
dp初始为 aim 大小且每个值为 -1 的数组,代码如下所示,具体思路可以参考《程序员代码面试指南》书籍

代码实现

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class solution {
public:
    int searchMoney(const vector<int>& vec, int aim) {
        if (0 == aim) {
            return 0;
        }
        vector<int> dp(aim + 1, -1);
        dp[0] = 0;
        
        for (int i = 1; i <= aim; i++) {
            for (int j = 0; j < vec.size(); j++) {
                if (i < vec[j]) {
                    // i小于 vec[j] 表示i无法由vec[j]组成
                    continue;
                } else if (i == vec[j]) {
                    // i 等于 vec[j] 表示i刚好可以由vec[j]组成
                    dp[i] = 1;
                } else if (dp[i - vec[j]] != -1){
                    // dp[i - vec[j]] 为-1的话,表示i - vec[j]无法组成
                    dp[i] = -1 == dp[i] ? dp[i - vec[j]] + 1 : min(dp[i], dp[i - vec[j]] + 1);                   
                }
            }      
        }   
        return dp[aim];
    }
};

int main(int argc, const char* argv[]) {
    //arr = [5, 2, 3] aim 为 20
    //arr = [5, 2, 3] aim 为 0
    //arr = [5, 3] aim 为 2
    solution a;
    vector<int> v1 = {5, 2, 3};
    cout << a.searchMoney(v1, 5) << endl;
    cout << a.searchMoney(v1, 0) << endl;
    cout << a.searchMoney(v1, 1) << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder567

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值