【leetcode】 322.零钱兑换 (动态规划,背包,广度优先搜索等多种解法,java实现)

本文详细探讨了LeetCode的322题——零钱兑换问题,通过动态规划、完全背包问题公式、广度优先遍历和记忆化递归四种方法进行了解决,每种方法都有详细的思路分析和Java代码实现。
摘要由CSDN通过智能技术生成
322. 零钱兑换

难度中等

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

示例 1:

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

示例 2:

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

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

方法一:动态规划

思路:

  • 看题目的问法,只问最优值是多少,没有要我们求最优解,一般情况下就是「动态规划」可以解决的问题;
  • 最优子结构其实比较明显,根据示例 1:
输入: coins = [1, 2, 5], amount = 11

凑成面值为 11 的最小***数可以由以下 33 者的最小值得到:

1、凑成面值为 10 的最小***数 + 面值为 1 的这一枚***;

2、凑成面值为 9 的最小***数 + 面值为 2 的这一枚***;

3、凑成面值为 6 的最小***数 + 面值为 5 的这一枚***;

dp[11] = min (dp[10] + 1, dp[9] + 1, dp[6] + 1)

  • 可以直接把题目的问法设计成状态。
第 1 步:定义「状态」

dp[i]:凑齐总价值 i需要的最少***数,状态就是问的问题。

第 2 步:写出「状态转移方程」

根据对具体例子的分析:

 dp[amount] = min(1 + dp[amount - coin[i]]) for i in [0, len - 1] if coin[i] <= amount

注意的是:

1、首先***的面值首先要小于等于***当前要凑出来的面值;

2、剩余的那个面值应该要能够凑出来,例如:求 dp[11] 需要参考 dp[10] ,如果不能凑出来的话,dp[10] 应该等于一个不可能的值,可以设计为 11 + 1,也可以设计为 -1 ,它们的区别只是在具体的代码编写细节上不一样而已。

再强调一次:新状态的值要参考的值以前计算出来的「有效」状态值。这一点在编码的时候需要特别注意。

因此,不妨先假设凑不出来,因为比的是小,所以设置一个不可能的数。

参考代码 1

  • Java
import java.util.Arrays;

public class Solution {
   

    public int coinChange(int[] coins, int amount) {
   
        // 给 0 占位
        int[] dp = new int[amount + 1];

        // 注意:因为要比较的是最小值,这个不可能的值就得赋值成为一个最大值
        Arrays.fill(dp, amount + 1);

        dp[0] = 0;

        for (int i = 1; i <= amount; i++) {
   
            for (int coin : coins) {
   
                if (i - coin >= 0 && dp[i - coin] != amount + 1) {
   
                    dp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值