[leetCode]322. 零钱兑换

题目

链接:https://leetcode-cn.com/problems/coin-change

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

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

示例 1:

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

动态规化

此题相当于完全背包问题,与01背包问题的不同在于,完全背包问题中的物品可以无限取,而01背包问题每个问题只能取一次或者不取。通过零一背包的状态转移方程可以推导出完全背包的状态转移方程:
f ( i , j ) = m a x ( f ( i − 1 , j ) , f ( i , j − v [ i ] ) + w [ i ] ) f(i,j) = max(f(i-1,j), f(i, j - v[i]) +w[i]) f(i,j)=max(f(i1,j),f(i,jv[i])+w[i])

背包问题需要注意题目问的是恰好放满背包还是,背包可以不放满,如果是恰好则初始化条件只能初始化 f ( 0... N , 0 ) 为 0 , f ( 0 , 1... V ) 为 无 解 ( + i n f i n i t y 或 者 − I n f i n i t y 根 据 题 目 求 最 大 还 是 最 小 初 始 化 ) f(0...N,0)为0, f(0, 1...V)为无解(+infinity 或者-Infinity根据题目求最大还是最小初始化) f(0...N,0)0,f(0,1...V)(+infinityInfinity);如果不要求背包被刚好放满则初始化条件为 f ( 0... N , 0 ) = 0 , f ( 0 , 1... V ) = 0 f(0...N, 0) = 0,f(0, 1...V) = 0 f(0...N,0)=0,f(0,1...V)=0

此题属于背包恰好放满的情况,下面是二维dp的代码

class Solution {
    public int coinChange(int[] coins, int amount) {
        // 物品的数量, 背包的大小为amount,
        //此题要求物品能恰好放满背包,所有只有dp[0][0] 为 1
        int N = coins.length;
        int[][] dp = new int[N + 1][amount + 1];
        Arrays.fill(dp[0],Integer.MAX_VALUE - 1);
        dp[0][0] = 0;
        for (int i = 1; i <= N; i++) {
            for (int j = 0; j <= amount; j++) {
                dp[i][j] = dp[i-1][j];
                if (j >= coins[i-1]) {
                    dp[i][j] = Math.min(dp[i][j], dp[i][j - coins[i-1]] + 1);
                }
            }
        }
        return dp[N][amount] == Integer.MAX_VALUE - 1 ? -1 : dp[N][amount];
    }
}

可以对上面的二维dp进行空间优化改为1维dp,改进后可以发现完全背包只需要将 0-1 背包的逆序遍历 dp 数组改为正序遍历即可。

class Solution {
    public int coinChange(int[] coins, int amount) {
        // 物品的数量, 背包的大小为amount,
        //此题要求物品能恰好放满背包,所有只有dp[0][0] 为 1
        int N = coins.length;
        int[] dp = new int[amount + 1];
        Arrays.fill(dp,Integer.MAX_VALUE - 1);
        dp[0] = 0;
        for (int i = 1; i <= N; i++) {
            for (int j = coins[i-1]; j <= amount; j++) {
                dp[j] = Math.min(dp[j], dp[j - coins[i-1]] + 1);
            }
        }
        return dp[amount] == Integer.MAX_VALUE - 1 ? -1 : dp[amount];
    }
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值