85、动态规划-零钱兑换

news2024/11/20 0:32:39

思路:

还是老样子,还是先使用递归方式来解,然后通过递归推动态规划。那递归如何设计?

定义一个递归方法:表示从index开始到N达到剩下的值(目标值减去上一步的值)做少可以得到数量是多少。int process(int[] coins, int index, int rest)。代码如下:

public static int coinChange(int[] coins, int amount) {
    // 如果硬币数组为空或长度为0,则无法进行兑换,返回-1
    if (coins == null || coins.length == 0) {
        return -1;
    }
    // 调用递归函数计算最少硬币数
    int result = process(coins, 0, amount);
    // 如果结果是Integer.MAX_VALUE,说明没有找到有效组合,返回-1
    return result == Integer.MAX_VALUE ? -1 : result;
}

private static int process(int[] coins, int index, int rest) {
    // 如果剩余金额为0,说明找到了一个有效的硬币组合,返回0(不需要更多硬币)
    if (rest == 0) {
        return 0;
    }
    // 如果硬币数组已经全部考虑完毕,或者剩余金额小于0,则当前路径不可行,返回Integer.MAX_VALUE
    if (index == coins.length || rest < 0) {
        return Integer.MAX_VALUE;
    }
    // 当前考虑的硬币
    int coin = coins[index];
    // 最多可以使用当前硬币的次数
    int zhang = rest / coin;
    // 初始化最小硬币数为最大整数,方便后面取最小值
    int min = Integer.MAX_VALUE;
    // 遍历每个可能的硬币数,从0开始到zhang
    for (int i = 0; i <= zhang; i++) {
        // 递归调用,计算使用下一个硬币种类时的结果
        int next = process(coins, index + 1, rest - coin * i);
        // 如果next不是Integer.MAX_VALUE,更新最小硬币数
        if (next != Integer.MAX_VALUE) {
            min = Math.min(min, i + next);
        }
    }
    // 返回找到的最小硬币数
    return min;
}

首先获取index下对应的值:coin=coins[index]   然后确定当前值最优可以用几张:zhang=rest/coin

然后设置一个最小值min;开始循环,如果使用当前值i张,那么一共需要多少张零钱。然后求一个最小值。最后返回min;

这里涉及到重复计算,比如数组 coins = [1, 2, 5], amount = 11

重复计算的例子:

  • 剩余金额为10时
    • 可能通过使用0个1元硬币后使用5个2元硬币到达,也可能通过使用10个1元硬币直接到达,都会调用 process(coins, 2, 10)
  • 剩余金额为9时
    • 可以通过使用1个1元硬币后使用4个2元硬币到达,或者通过9个1元硬币到达,都会调用 process(coins, 2, 9)
  • 剩余金额为5时
    • 可以通过使用1个5元硬币直接到达,或者使用5个1元硬币,或者使用3个1元硬币后使用1个2元硬币到达,这些都会重复调用 process(coins, 2, 5)

所以我们可以使用动态规划来解,首先对于这种稍微服务在可以的画一个表格:

行:表示可以使用的元素   列:目标值是多少

dp[i][j]:表示对于数组中的元素从0到i可以用 得到j最少多少张。表格如下:

01234567891011
101234567891011
2011223344556
5011221223323

找规律:对于dp[i][j]是不使用当前值 nums[i] 达到小还是使用当前值dp[i][j-nums[i]+1 小谁小要谁。

代码如下:

public static int coinChange(int[] coins, int amount) {
        if (coins == null || coins.length == 0) {
            return -1;
        }
        int N = coins.length;
        int[][] dp = new int[N][amount + 1];
        // dp[i][j] 表示在下标 0-i这个数组里面 最少需要多少张可以组成j
        // dp[i][0]==0 java 默认 不用写
        // 计算dp[0][j] 表示只有一个数的 最少有多少种张组成 那就是能否整除
        for (int i = 1; i <= amount; i++) {
            if (i % coins[0] == 0) {
                dp[0][i] = i / coins[0];
            } else {
                dp[0][i] = -1;
            }
        }
        //
        for (int i = 1; i < N; i++) {
            for (int j = 1; j <= amount; j++) {
                dp[i][j] = Integer.MAX_VALUE;
                if (dp[i - 1][j] != -1) {
                    dp[i][j] = dp[i - 1][j];
                }
                if (j - coins[i] >= 0 && dp[i][j - coins[i]] != -1) {
                    dp[i][j] = Math.min(dp[i][j], dp[i][j - coins[i]]+1);
                }
                if (dp[i][j] == Integer.MAX_VALUE) {
                    dp[i][j] = -1;
                }
            }
        }
        return dp[N - 1][amount];
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1642027.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速幂笔记

快速幂即为快速求出一个数的幂&#xff0c;这样可以避免TLE&#xff08;超时&#xff09;的错误。 传送门&#xff1a;快速幂模板 前置知识&#xff1a; 1) 又 2) 代码&#xff1a; #include <bits/stdc.h> using namespace std; int quickPower(int a, int b) {int…

STM32单片机wifi云平台+温度+烟雾+火焰+短信+蜂鸣器 源程序原理图

目录 1. 整体设计 2. 液晶显示 3. Ds18b20温度传感器 4. Mq2烟雾传感器 5. 火焰传感器传感器 6. 蜂鸣器驱动控制 7. 按键 8. Gsm短信模块 9. Esp8266wifi模块 10、源代码 11、资料内容 资料下载地址&#xff1a;STM32单片机wi…

PR2019新建项目教程

一&#xff0c;新建项目&#xff1a; 设置工程名称&#xff0c;选择工程目录位置&#xff0c;其他默认&#xff1a; 二&#xff0c;新建序列 新建项->序列&#xff1a; 设置序列参数&#xff1a; 三&#xff0c;导出设置 设置导出参数&#xff1a;

vivado Aurora 8B/10B IP核(11)- 共享逻辑(Share Logic)

Vivado IDE 中的共享逻辑选项配置核心&#xff0c;包括可收集的资源&#xff0c;如收发器四路 PLL&#xff08;QPLL&#xff09;&#xff0c;收 发器差分缓冲区&#xff08;IBUFDS_GTE2&#xff09;以及核心或示例设计中的时钟和复位逻辑。 当选择了核心选项中的包含共享逻辑时…

QT防止自研软件被复制的基本操作(二)

参考一 自研软件为了防止被人任意复制传播&#xff0c;需要设置注册使用模式。基本原理&#xff1a;通过计算机的特异性编号&#xff0c;加上自己的编码&#xff0c;使用加密算法算出一个生成码。 一、计算机的特异性编号 硬盘的编号&#xff1a;最后一块硬盘的编号就行&#…

linux的基础入门(2)

环境变量 在Shell中&#xff0c;正确的赋值语法是没有空格的&#xff0c;即变量名数值。所以&#xff0c;正确的方式是&#xff1a; tmpshy 这样就将变量tmp赋值为"shy"了。 注意&#xff1a;并不是任何形式的变量名都是可用的&#xff0c;变量名只能是英文字母、…

开源AI名片商城小程序:打造卓越客户体验,引领留存与增长新潮流

在快速变化的商业环境中&#xff0c;如何有效地吸引并留住客户已成为每个企业面临的重要课题。为此&#xff0c;我们精心打造了一款创新的解决方案——开源AI名片商城小程序&#xff0c;它将内容培育、社交互动、产品展示与购买功能融为一体&#xff0c;为您的客户带来前所未有…

PS超美古风毛笔字体300款,PS毛笔字体笔触与笔刷素材

一、素材描述 本套PS素材&#xff0c;大小1.66G&#xff0c;2个压缩文件。 二、素材目录 &#xff08;一&#xff09;、PS毛笔字体笔触与笔刷素材.rar&#xff08;163.5M&#xff09; &#xff08;二&#xff09;、PS超美古风毛笔字体300款.rar&#xff08;1.5G&#xff09…

2.1 上海雷卯电子PLC

PLC&#xff08;可编程逻辑控制器&#xff09;像是工厂自动化系统的“大脑”&#xff0c;负责监控和控制各种生产过程。PLC 能够精确地协调各类设备的操作&#xff0c;实现生产流程的自动化和优化。通过编程&#xff0c;它可以根据不同的生产需求灵活调整控制逻辑&#xff0c;提…

【数据结构】这里有一份KMP算法优化的详细攻略,不要错过哦!!!

KMP算法优化 导读一、C语言实现next数组1.1 next数组的底层逻辑1.2 串的数据类型的选择1.3 函数三要素1.3.1 查漏补缺——数组传参1.3.2 小结 1.4 函数主体1.4.1 通过模拟实现1.4.1.1 算法思路1.4.1.2 代码实现1.4.1.3 算法测试 1.4.2 算法的缺陷1.4.3 算法优化1.4.3.1 算法思路…

蛇鹭优化算法(SBOA)-2024年4月SCI新算法-公式原理详解与性能测评 Matlab代码免费获取

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 一、初始化阶段 二、蛇鹭的捕猎…

CSS精灵图、字体图标、HTML5新增属性、界面样式和网站 favicon 图标

精灵图 为什么要使用精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度,因此&#xff0c;为了有效地减少服务…

C++校招八股

c类的访问权限与继承方式 公有成员在任何地方都可以被访问&#xff0c;包括类的外部和派生类。受保护成员在类的内部和派生类中可以被访问&#xff0c;但在类的外部不可访问。 私有成员只能在类的内部访问&#xff0c;包括类的成员函数和友元函数&#xff0c;不允许在类的外部…

应用分层和企业规范

目录 一、应用分层 1、介绍 &#xff08;1&#xff09;为什么需要应用分层&#xff1f; &#xff08;2&#xff09;如何分层&#xff1f;&#xff08;三层架构&#xff09; MVC 和 三层架构的区别和联系 高内聚&#xff1a; 低耦合&#xff1a; 2、代码重构 controlle…

【软件测试】测试用例设计方法

1. 等价类划分法1.1. 等价类划分法的定义1.2. 有效等价类和无效等价类1.3. 等价类划分法实例分析 2. 边界值分析法2.1. 边界值分析法的定义2.2. 边界点2.3. 边界值法实例分析 3. 判定表法3.1. 如何用判定表法设计测试用例3.2. 判定表法实例分析 4. 正交表法4.1. 什么是正交表4.…

模拟实现memcpy,memmove,memset,memcmp

memcpy void * memcpy ( void * destination, const void * source, size_t num ); 使用注意事项&#xff1a; 从source的位置向后复制num个字节数据到destination所指向的内存位置中。 这个函数遇到如果源空间和⽬标空间出现重叠&#xff0c;就得使⽤memmove函数处理。 …

纯血鸿蒙APP实战开发——自定义路由栈管理

介绍 本案例将介绍如何使用路由跳转返回时获取到来源页的模块名以及路径名&#xff0c;在实际场景中同一页面通常会根据不同来源页展示不同的UI。 使用说明 无特殊使用说明&#xff0c;其他使用说明参考动态路由的相关说明 实现思路 路由来源页的实现 新增来源页字段 ex…

【刷题篇】动态规划-二维费用的背包问题(十二)

文章目录 1、一和零2、盈利计划3、组合总和 Ⅳ4、不同的二叉搜索树(卡特兰数) 1、一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#x…

vue快速入门(五十三)使用js进行路由跳转

注释很详细&#xff0c;直接上代码 上一篇 新增内容 几种常用的路由跳转方式演示 源码 App.vue <template><div id"app"><div class"nav"><!-- router-link 自带两个高亮样式类 router-link-exact-active和router-link-active区别&a…

AI代理架构的发展:从单一到多代理系统的演进及其影响分析

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…