算法笔记_048:找零问题(Java)

目录

1 问题描述

2 解决方案

2.1 动态规划法

 


1 问题描述

现需找零金额为n,则最少需要用多少面值为d1 < d2 < d3 < ... < dm的硬币?(PS:假设这m种面值d1 < d2 < d3 < ... < dm的硬币,其中d1 = 1,且每种硬币数量无限可得)


2 解决方案

2.1 动态规划法

本文编码思想参考自《算法设计与分析基础》第三版,具体讲解如下:

具体代码如下:

package com.liuzhen.chapter8;

public class ChangeMaking {

    public void getChangeMakingN(int[] coinType,int n){
        int[] minNumber = new int[n+1];   //初始化后,所有元素均为0,其中minNumber[0] = 0,表示无须找零
        int[] tempMinJ = new int[n+1];    //tempMinJ[0]在此处无含义
        for(int i = 1;i <= n;i++){
            int j = 0;
            int tempJ = -1;      //用于h获取minNumber[i]最小值中当前新使用的硬币面值数组下标
            int temp = Integer.MAX_VALUE;        //计算当前minNumber[i]最小值,初始化int类型最大值
            while(j < coinType.length && i >= coinType[j]){
                if(minNumber[i-coinType[j]] + 1 < temp){
                    temp = minNumber[i-coinType[j]] + 1;
                    tempJ = j;
                }
                j++;
            }
            minNumber[i] = temp;
            tempMinJ[i] = tempJ;
        }

        System.out.println("给定硬币面值种类依次为:");
        for(int i = 0;i < coinType.length;i++)
            System.out.print(coinType[i]+" ");

        System.out.println("\n找零大小从1到"+n+"的最少硬币组合数目为:");
        for(int i = 1;i < minNumber.length;i++)
            System.out.print(minNumber[i]+" ");

        System.out.println("\n对应找零大小从1到"+n+"新增的硬币数组下标为:");
        for(int i = 1;i < tempMinJ.length;i++)
            System.out.print(tempMinJ[i]+" ");

        System.out.println("\n对应找零大小从1到"+n+"新增的硬币数组下标对应的硬币面值为:");
        for(int i = 1;i < tempMinJ.length;i++)
            System.out.print(coinType[tempMinJ[i]]+" ");

        System.out.println("\n\n找零大小为"+n+"的硬币组合最少数目为:"+minNumber[minNumber.length-1]);
        System.out.print("找零大小为"+n+"的硬币组合最少数目对应的硬币面值依次为:");
        int needN = n;
        int minJ = tempMinJ.length-1;
        while(needN > 0){
            System.out.print(coinType[tempMinJ[minJ]]+" ");
            needN = needN - coinType[tempMinJ[minJ]];
            minJ = needN;
        }
    }

    public static void main(String[] args){
        ChangeMaking test = new ChangeMaking();
        int[] coinType = {1,3,4};
        test.getChangeMakingN(coinType, 6);
    }
}

运行结果:

给定硬币面值种类依次为:
1 3 4
找零大小从1到6的最少硬币组合数目为:
1 2 1 1 2 2
对应找零大小从1到6新增的硬币数组下标为:
0 0 1 2 0 1
对应找零大小从1到6新增的硬币数组下标对应的硬币面值为:
1 1 3 4 1 3 

找零大小为6的硬币组合最少数目为:2
找零大小为6的硬币组合最少数目对应的硬币面值依次为:3 3 

参考资料:

1.算法设计与分析基础(第3版)  Anany Levitin 著 潘彦 译

时间: 2024-10-05 23:27:17

算法笔记_048:找零问题(Java)的相关文章

算法笔记——硬币找零之最少硬币数

题目来源:NYOJ995 问题描述: 在现实生活中,我们经常遇到硬币找零的问题,例如,在发工资时,财务人员就需要计算最少的找零硬币数,以便他们能从银行拿回最少的硬币数,并保证能用这些硬币发工资. 我们应该注意到,人民币的硬币系统是 100,50,20,10,5,2,1,0.5,0.2,0.1,0.05, 0.02,0.01 元,采用这些硬币我们可以对任何一个工资数用贪心算法求出其最少硬币数. 但不幸的是: 我们可能没有这样一种好的硬币系统, 因此用贪心算法不能求出最少的硬币数,甚至有些金钱总数还

贪心算法解硬币找零问题

假如有一种货币,它有面值为1分.2分.5分和1角的硬币,最少需要多少个硬币来找出K分钱的零钱? 按照贪心算法的思想,需要不断地使用面值最大的硬币.如果要找零的值小于最大的硬币值,则尝试第二大的硬币,依次类推. 代码如下: #include <iostream> using namespace std; #define ONE 1 #define TWO 2 #define FIVE 5 #define TEN 10 int main() { int money; int one=0,two=0

算法笔记_023:拓扑排序(Java)

目录 1 问题描述 2 解决方案 2.1 基于减治法实现 2.2 基于深度优先查找实现 1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面. 2 解决方案 2.1 基于减治法实现 实现原理:不断地做这样一件事,在余下的有向图中求取一个源(source)(PS:定义入度为0的顶点为有向图的源),它是一个没有输入边的顶点,然后把它和所有从它出发

贪心算法解决钱币找零问题

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Coin { class Program { static void Main(string[] args) { int[] value = new int[] { 1, 2, 5, 10, 20, 50, 100 }; int[] count =

算法笔记_132:最大流量问题(Java)

目录 1 问题描述 2 解决方案   1 问题描述 何为最大流量问题? 给定一个有向图,并为每一个顶点设定编号为0~n,现在求取从顶点0(PS:也可以称为源点)到顶点n(PS:也可以称为汇点)后,顶点n能够接收的最大流量.图中每条边的权值为该边的容量,从顶点0到顶点n的某一条路径中最大流量不能超过该路径中任何一条边剩下的容量. 2 解决方案 上述对于最大流量问题的描述是楼主自己个人描述,描述的有点粗暴简略>~<. 求取最大流量问题的的核心要理解三个概念: (1)残留网络 (2)增广路径 (3)

算法笔记_124:密码脱落(Java)

一 问题描述 X星球的考古学家发现了一批古代留下来的密码.这些密码是由A.B.C.D 四种植物的种子串成的序列.仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串).由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征. 你的任务是:给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子. 输入一行,表示现在看到的密码串(长度不大于1000)要求输出一个正整数,表示至少脱落了多少个种子. 例如,输入:ABCBA则程序应该输出:0 再例

算法笔记_027:俄式乘法(Java)

1 问题描述 首先,了解一下何为俄式乘法?此处,借用<算法设计与分析基础>第三版上一段文字介绍: 2 解决方案 具体编码如下: package com.liuzhen.chapter4; public class RussianPeasant { //方法1:递归求解 public void recursionRussian(int m,int n,int result){ if(m < 1) return; if(m == 1) System.out.println("使用递

算法笔记_016:凸包问题(Java)

目录 1 问题描述 2 解决方案 2.1 蛮力法 1 问题描述 给定一个平面上n个点的集合,它的凸包就是包含所有这些点的最小凸多边形,求取满足此条件的所有点. 另外,形象生动的描述: (1)我们可以把这个问题看作如何用长度最短的栅栏把n头熟睡的老虎围起来. (2)也可以这样看:请把所讨论的点想象成钉在胶合板上的钉子,胶合板代表平面.撑开一根橡皮筋圈,把所有的钉子都围住,然后啪一声松开手.凸包就是以橡皮圈为边界的区域.具体示意如下图1所示: 图1  用橡皮筋来解释凸包 2 解决方案 2.1 蛮力法

算法笔记_042:求最小公倍数(Java)

目录 1 问题描述 2 解决方案   1 问题描述 何为最小公倍数?能同时被数字m和数字n整除的最小整数.例如,24和60的最小公倍数等于120.下面请编写相关函数实现求取数字m和n的最小公倍数. 2 解决方案 关于本文求解最小公倍数的思想,来自于<算法设计与分析基础>第三版上一段讲解,具体如下: 具体代码如下: package com.liuzhen.chapter6; public class LeastCommonMultiple { //使用欧几里得算法求解数m和数n最大公约数 pub