零钱兑换||

题目

零钱兑换||

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。
假设每一种面额的硬币有无限个。
题目数据保证结果符合 32 位带符号整数。

示例

image

解题思路1

1.该题木我们可以使用递归算法进行暴力求解。
2.根据题目可以知道,每个硬币可以重复使用。
3.此时我们可以使用递归回溯算法。

for(int i = start; i < coins.size(); i++){
            getNumberchange(coins, cnt, amount, value+coins[i], i);
        }

4.其中cnt表示满足条件个数,coins表示硬币集合。amount表示目标金额。value+cons[i]:表示当前组合的和。i:表示下一次从什么面额金额开始。

实现代码

class Solution {
public:
    void getNumberchange(const vector<int> & coins, int & cnt, int amount, int value, int start){
        if(value >= amount) {
            if(value == amount) cnt++;
            return ;
        }
        for(int i = start; i < coins.size(); i++){
            getNumberchange(coins, cnt, amount, value+coins[i], i);
        }
    }
    int change(int amount, vector<int>& coins) {
        int cnt = 0;
        getNumberchange(coins, cnt, amount, 0, 0);
        return cnt;
    }
};

解题思路2

1.第二种方法,我们采用动态规划解题。
2.根据题目可知,每种面额的金币可以重复使用。
3.与传统0-1背包问题,我们可以将面额硬币重复使用。

//代码1
for(int k = coins[i]; k <= amount; k++){
       dp[k] = dp[k] + dp[k-coins[i]];
    }
//代码2
for(int k = amount; k >= coins[i]; k--){
        dp[k] = dp[k] + dp[k-coins[i]];
    }

4.代码1部分表示相同硬币使用金额可以反复使用。
5.代码2部分表示相同硬币使用时,只能使用一次。

实现代码

class Solution {
public:
   
    int change(int amount, vector<int>& coins) {
        vector<unsigned long long> dp(amount+1, 0);
        dp[0] = 1; 
        for(int i = 0; i < coins.size(); i++){
            for(int k = coins[i]; k <= amount; k++){
                dp[k] = dp[k] + dp[k-coins[i]];
            }
        }
        return dp[amount];
    }
};
posted @ 2026-03-13 10:56  heyuikn  阅读(1)  评论(0)    收藏  举报