(LeetCode 热题 100)322. 零钱兑换(动态规划dp ||递归+记忆化dfs)

题目:322. 零钱兑换

在这里插入图片描述

方法一:动态规划dp+完全背包问题。
Acwing算法基础课 第五讲 动态规划:前四题都是背包问题

C++版本:

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
    	//状态f[i]表示:凑成金额i的最少硬币个数
        vector<int> f(amount+1,amount+10);//置为amount+10表示不可能组合成该金额
        //初始化边界
        f[0]=0;
        //第一层for循环枚举所有硬币
        for(int i=0;i<coins.size();i++){
        	//完全背包问题
            for(int j=coins[i];j<=amount;j++){
                f[j]=min(f[j],f[j-coins[i]]+1);
            }
        }
        return f[amount]==amount+10 ? -1: f[amount];
    }
};

JAVA版本:

class Solution {
    public int coinChange(int[] coins, int amount) {
    	//状态f[i]表示:凑成金额i的最少硬币个数
        int[] f=new int[amount+1];
        //置为amount+1表示不可能组合成该金额
        Arrays.fill(f,amount+10);
        //初始化边界
        f[0]=0;
        //第一层for循环枚举所有硬币
        for(int i=0;i<coins.length;i++){
        	//完全背包问题
            for(int j=coins[i];j<=amount;j++){
                f[j]=Math.min(f[j],f[j-coins[i]]+1);
            }
        }
        return f[amount]==amount+10? -1:f[amount];
    }
}

第一层for循环也可以枚举amount

C++版本:

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> f(amount+1,amount+10);
        f[0]=0;
        //第一层for循环枚举amount
        for(int i=1;i<=amount;i++){
            for(int j=0;j<coins.size();j++){
                if(coins[j]<=i) f[i]=min(f[i],f[i-coins[j]]+1);
            }
        }
        return f[amount]==amount+10 ? -1: f[amount];
    }
};

JAVA版本:

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] f=new int[amount+1];
        Arrays.fill(f,amount+10);
        f[0]=0;
        //第一层for循环枚举amount
        for(int i=1;i<=amount;i++){
            for(int j=0;j<coins.length;j++){
                if(coins[j]<=i) f[i]=Math.min(f[i],f[i-coins[j]]+1);
            }
        }
        return f[amount]==amount+10? -1:f[amount];
    }
}

方法二:递归+记忆化dfs。

C++版本:

class Solution {
public:
	//记忆化数组sta
    vector<int> sta;
    int dfs(vector<int>& coins, int amount){
    	//小于0,表明不符合
        if(amount<0) return -1;
        //等于0,表明符合
        if(amount==0) return 0;
        //遍历过
        if(sta[amount]!=0) return sta[amount];
        //最小值
        int mn=INT_MAX;
        //枚举所有可能的硬币
        for(int i=0;i<coins.size();i++){
            int tmp=dfs(coins,amount-coins[i]);
            //-1表明该条路线不可
            if(tmp==-1) continue;
            mn=min(mn,tmp+1);
        }
        return sta[amount]= mn==INT_MAX? -1:mn;
    }
    int coinChange(vector<int>& coins, int amount) {
    	
        sta.resize(amount+1);
        //memset(sta,-1,sizeof sta);
        return dfs(coins,amount);
    }
};

JAVA版本:

class Solution {
	//记忆化数组sta
    private int[] sta;
    private int dfs(int[] coins, int amount){
    	//小于0,表明不符合
        if(amount<0) return -1;
        //等于0,表明符合
        if(amount==0) return 0;
        //遍历过
        if(sta[amount]!=0) return sta[amount];
        //最小值
        int mn=Integer.MAX_VALUE;
        //枚举所有可能的硬币
        for(int i=0;i<coins.length;i++){
            int tmp=dfs(coins,amount-coins[i]);
            //-1表明该条路线不可
            if(tmp==-1) continue;
            mn=Math.min(mn,tmp+1);
        }
        return sta[amount]= mn==Integer.MAX_VALUE? -1:mn;
    }
    public int coinChange(int[] coins, int amount) {
        sta=new int[amount+1];
        //置为0,表示没有遍历过
        Arrays.fill(sta,0);
        return dfs(coins,amount);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值