动态规划之找零钱问题(求最小硬币数)

这篇具有很好参考价值的文章主要介绍了动态规划之找零钱问题(求最小硬币数)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目:零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 0 。你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1

首先我先阐述一下我对于动态规划的一些理解:
1.动态规划是通过运用结果集中产生的最优结果去推出下一需要的结果,即用0 ~ (n - 1)结果间结果的规律推出第n个结果。
2.动态规划通过计算最优解的值,通常自底向上或者自顶向下
3.动态规划就是将大问题分成小问题求解,将一个个小问题的解组合求得大问题的解。
我的理解暂时就是这么多,毕竟也是萌新。

题目分析:刚看问题感觉通过贪心算法也能求出来,但是如果coins = [5,3], amount = 9 的话会发现求不出来。这题用动态分析求的话我们要明白要求的结果集是什么,此题目的结果集是求0 ~amount 下可用的当前可用最少硬币(coins ),得result[i][j],i代表当前0 ~ i的可用硬币,j代表当前所求金额。我们通过表格寻找result[i][j]结果与result[0 ~ i][0 ~ j]间的关系,如下图:
动态规划之找零钱问题(求最小硬币数)
动态规划之找零钱问题(求最小硬币数)

分析:
1)对于coins硬币数组中有的是用与不用的区别
2)对于j >= 3的结果集中,我们发现amount (3)= amount (1)+ amount (2);amount (7)= amount (6)+ amount (1),amount (7)= amount (5)+ amount (2),amount (7)=amount (3)+ amount (4)…等这样的规律。为什么不说amount (9)= amount (3)*3呢,因为结果是和amount (6)+ amount (3)是一样的所以就不考虑了。

所以我们得出 result[i][j]结果与result[0 ~ i][0 ~ j]间的关系:

当 amount == coins[i]时,就取1;

当 amount != coins[i]时,就取组合结果中最小的数(参考分析结论2中的组合结果,注意考虑0,关于怎么求最小结果我就直接用代码展示了);

测试如下:
动态规划之找零钱问题(求最小硬币数)
动态规划之找零钱问题(求最小硬币数)
代码如下:

package 算法.动态规划;

import java.util.Scanner;

/*
*  零钱兑换
*
* */
public class AskingChange {
    int amount;
    int[] coins;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int amount = scanner.nextInt();
        AskingChange askingChange = new AskingChange(amount);
        int coinsNumbers = scanner.nextInt();
        // 下标从1开始
        int[] coins = new int[coinsNumbers + 1];
        for (int i = 1; i < coins.length; i++) {
        		coins[i] = scanner.nextInt();
        	}
        askingChange.setCoins(coins);
        // 结果记录
        int[][] result = new int[coins.length][amount+1];

        askingChange.getMinCoins(coins.length-1, amount, result);
        System.out.println(result[coins.length-1][amount]);
        scanner.close();
    }

    public void getMinCoins(int coinsIndex,int amountLength,int[][] result){
        // 外层的for表示开放的coins可用数
        for (int i = 1; i <= coinsIndex; i++) {
        		for (int j = 1; j <= amountLength; j++) {
                    for (int k = 1; k <= i; k++) {
                        // 刚好等于面额
                        if (j == coins[k]) {
                            result[i][j] = 1;
                            break;
                        }
                        if (j != coins[k]) {
                            result[i][j] = getMin(result[i],j);
                        }
                    	}
        			}
        	}
    }

    // 获取0到i中组合方法的最小硬币数
    public int getMin(int[] result,int resultLength) {
        int min ;
        if (resultLength <= 1){
            return 0;
        }else if (resultLength ==2) {
            return result[1] * 2;
        }
        min = result[1]+result[resultLength-1];
        // 如果没结果
        if ((result[1] == 0) | (result[resultLength-1] == 0)){
            // 赋予int最大值的
            min = 2147483647;
        }
        for (int i = 1; i <= resultLength / 2; i++) {
                    // 跳过无结果的数
                    if ((result[i] == 0) | (result[resultLength - i] == 0)) {
                        continue;
                    }
            		if (min > (result[i] + result[resultLength - i])) {
            		    min = result[i] + result[resultLength - i];
                    }
            	}
        if (min == 2147483647){
            min = 0;
        }
        return min;
    }

    public AskingChange(int amount) {
        this.amount = amount;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }

    public int[] getCoins() {
        return coins;
    }

    public void setCoins(int[] coins) {
        this.coins = coins;
    }
}

后来我发现其实用一维数组记录结果集也可以,就是不限制硬币必须从0~ i依次解开封印,而是可以直接用coins内所有的硬币,但是懒癌发作就懒得改了。写下博客记录一下学习过程,如果其中有什么说得不对的,望各位大佬指出。文章来源地址https://www.toymoban.com/news/detail-472799.html

到了这里,关于动态规划之找零钱问题(求最小硬币数)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【十九】【动态规划】518. 零钱兑换 II、279. 完全平方数、474. 一和零,三道题目深度解析

    动态规划就像是解决问题的一种策略,它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题,并将每个小问题的解保存起来。这样,当我们需要解决原始问题的时候,我们就可以直接利用已经计算好的小问题的解,而不需要重

    2024年02月03日
    浏览(40)
  • 动态规划——零钱兑换问题

    1、题目 :力扣原题 2、分析 (1)结合我们之前分析的(动态规划解决背包问题),这里硬币有无限个对应完全背包问题。但又存在一点区别: 纯完全背包是能否凑成总的金额,本题是要求凑成总金额的组合个数 。 (2)要注意是求解组合 还是排列 问题。例如 221 和121可以

    2024年02月04日
    浏览(39)
  • 零钱兑换,凑零钱问题,从暴力递归到动态规划(java)

    322 零钱兑换 - 可以打开链接测试 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。 你可以认为每种硬币的数量是无限的。 示例 1:

    2024年02月07日
    浏览(38)
  • 【LeetCode题目详解】第九章 动态规划part06 完全背的讲解 518. 零钱兑换 II 377. 组合总和 Ⅳ (day44补)

    # 完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 每件物品都有无限个(也就是可以放入背包多次) ,求解将哪些物品装入背包里物品价值总和最大。 完全背包和01背包问题唯一不同的地方就是,每种物品有无限件 。

    2024年02月09日
    浏览(38)
  • 《程序员面试金典(第6版)》 面试题 08.11. 硬币(动态规划,组合问题,C++)

    硬币。给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。(结果可能会很大,你需要将结果模上1000000007) 示例1: 输入: n = 5 输出:2 解释: 有两种方式可以凑成总金额: 5=5 5=1+1+1+1+1 示例2: 输入: n = 10 输出:4 解释: 有四种方式可以凑成总金额: 1

    2023年04月08日
    浏览(55)
  • 【LeetCode动态规划#08】完全背包问题实战与分析(零钱兑换II)

    力扣题目链接(opens new window) 给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 示例 1: 输入: amount = 5, coins = [1, 2, 5] 输出: 4 解释: 有四种方式可以凑成总金额: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1 示例 2: 输入: amount = 3

    2023年04月19日
    浏览(47)
  • LeetCode518. 零钱兑换 II 以及 动态规划相关的排列组合问题

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

    2024年02月09日
    浏览(42)
  • 力扣算法刷题Day44|动态规划:完全背包问题 零钱兑换II 组合总和Ⅳ

    力扣题目:#518.零钱兑换II(完全背包组合问题) 刷题时长:7min 解题方法:动态规划(完全背包) 复杂度分析 时间复杂度: O(mn),其中 m 是amount,n 是 coins 的长度 空间复杂度: O(m) 问题总结 对递推公式的理解 本题收获 题意转换:纯完全背包是凑成背包最大价值是多少,而本

    2024年02月13日
    浏览(42)
  • 【LeetCode动态规划#08】完全背包问题实战与分析(零钱兑换II--求组合、组合总和IV--求排列)

    力扣题目链接(opens new window) 给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 示例 1: 输入: amount = 5, coins = [1, 2, 5] 输出: 4 解释: 有四种方式可以凑成总金额: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1 示例 2: 输入: amount = 3

    2023年04月19日
    浏览(42)
  • 【LeetCode题目详解】第九章 动态规划part01 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯 (day38补)

    斐波那契数  (通常用  F(n) 表示)形成的序列称为 斐波那契数列 。该数列由  0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: 给定  n ,请计算 F(n) 。 示例 1: 示例 2: 示例 3: 提示: 0 = n = 30 斐波那契数列大家应该非常熟悉不过了,非常适合作为动规第

    2024年02月07日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包