从零学算法322

322.给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins = [2], amount = 3
输出:-1
示例 3:
输入:coins = [1], amount = 0
输出:0

  • 动态规划:假设 dp[i] 为 amount 为 i 时的最少硬币数。那么我们首先可以知道的是 dp[0] = 0,并且 dp[coin] = 1,比如硬币面额 coin 为 2,那么 dp[2] 一定为 1,一个 2 元硬币就能使得总和为 2。那么 dp[i] 呢,最好的结果肯定是 dp[i-coin] + 1,比如你有 [1,2,5] 三种硬币, 当你要凑到 7 元时你会想,如果我们得到了凑成 6 元的最小硬币数,再加一个 1 元硬币就得到了凑成 7 元的一种可能,即 dp[7] = dp[7-1] + 1,或者我们之前已经得到了凑成 5 元的最小硬币数,再加一个 2 元硬币也能凑成 7 元,即 dp[7] = dp[7-2] + 1,我们取 min 即可
  •   public int coinChange(int[] coins, int amount) {int[] dp = new int[amount+1];Arrays.fill(dp, -1);dp[0] = 0;for(int c:coins){// 硬币面值首先肯定得小于等于我所需的总数if(c<=amount)dp[c]=1;}for(int i=1;i<=amount;i++){// 得到过了就跳过if(dp[i]!=-1)continue;int min = Integer.MAX_VALUE;for(int c:coins){// 我们需要得到总共 i 元,硬币面额肯定首先得小于 i,等于的我们已经初始化过了// 并且我们在计算比如 dp[7] = dp[7-2] + 1 时,我们肯定首先得保证 dp[7-2] 存在// 不然怎么往后推if(c < i && dp[i-c]!=-1)min=Math.min(min,dp[i-c]);}if(min != Integer.MAX_VALUE)dp[i]=min+1;}return dp[amount];}
    
  • 这里附上别人更简洁的写法,无法凑成的情况就用 int 最大值表示
  •   public int coinChange(int[] coins, int amount) {if(coins.length == 0){return -1;}//dp[i]表示金额i最少需要的硬币数int[] dp = new int[amount+1];dp[0] = 0;for(int i=1;i<=amount;i++){int min = Integer.MAX_VALUE;for (final int coin : coins) {// 这里 dp[i - coin] < min 不仅能得出更少硬币数// 而且因为无法凑成的 dp[x] 为 int 最大值,所以 dp[x] 如果凑不成就不可能 < min// 所以它同时也排除了无法凑成的情况// 当然你也可以改写成  // if (i - coin >= 0) min = Math.min(min,dp[i - coin]);// 然后 min 不为 int 最大值才 + 1,否则上面就加 1 就超出 int 最大值了// dp[i] = min!=Integer.MAX_VALUE?min+1:Integer.MAX_VALUE;if (i - coin >= 0 && dp[i - coin] < min) {min = dp[i - coin] + 1;}}dp[i] = min;}return dp[amount]== Integer.MAX_VALUE ? -1 : dp[amount];}
    
  • dfs(超时):我们很容易想到的就是像 n 叉树一样尝试每种组合,比如 [1,2] 我们从这两个硬币开始分叉
  • (1|2) -> (11,12 | 21,22) -> (111,112 | 121,122 | 211,212 | 221,222)......
  •   int MAX = Integer.MAX_VALUE;int[] coins;int ans=MAX;public int coinChange(int[] coins, int amount) {this.coins = coins;dfs(amount,0);return ans==MAX?-1:ans;}// amount:所需总数// count:硬币数量public void dfs(int amount,int count){// 减到总数小于 0 肯定不行if(amount < 0)return;// 减到总数为 0 说明凑出一种可能了,记录下来if(amount==0){ans=Math.min(ans,count);   }for(int coin:coins){dfs(amount-coin, count+1);}}
    
  • 上面代码会超时,是因为其实组成比如12 和 21 时得到的总数是相同的都是总共 3 元,所以会包含大量重复的计算,那么我们很容易想到的就是用记忆化搜索改进,其实这和 dp 的原理很像
  •   int MAX = Integer.MAX_VALUE;int[] coins;int[] memo;public int coinChange(int[] coins, int amount) {memo = new int[amount+1];this.coins = coins;return dfs(amount);}public int dfs(int amount){if(amount == 0)return 0;if(amount < 0)return -1;// 有了这个我们才减少了很多重复计算if(memo[amount] != 0)return memo[amount];int min = MAX;for(int coin:coins){int res = dfs(amount-coin);// res == -1 可以理解为 dp[amount-coin] 不存在,所以你会发现记忆化搜索都能改写成 dp// 所以 dp[amount-coin] 存在才能推出在此基础上加一个 coin 凑成 amount,推出 dp[amount]if(res!=-1)min = Math.min(min,res);}// 每个 coin 对应的 dp[amount-coin] 都不存在时 min 就保持不变还是 int 最大值// 这就表示我们无法用这些硬币得到总数 amount,所以为 -1memo[amount]=min==MAX?-1:min+1;return memo[amount];}
    

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

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

相关文章

【LeetCode】无权图的最短路精选7题——单源、多源

目录 无权图的单源最短路问题&#xff1a; 1. 迷宫中离入口最近的出口&#xff08;中等&#xff09; 2. 最小基因变化&#xff08;中等&#xff09; 3. 单词接龙&#xff08;困难&#xff09; 4. 为高尔夫比赛砍树&#xff08;困难&#xff09; 无权图的多源最短路问题&a…

疾控中心污水采样过程中会遇到哪些困难

在疾控中心的污水采样过程中&#xff0c;可能会遇到多种困难。 首先&#xff0c;污水的成分可能非常复杂&#xff0c;包括各种细菌、病毒、寄生虫、重金属、化学物质等&#xff0c;这给采样带来了很大的挑战。其次&#xff0c;污水中的有害物质可能会对采样设备和人员造成损害…

嘎嘎嘎嘎嘎嘎嘎

☞ 通用计算机启动过程 1️⃣一个基础固件&#xff1a;BIOS 一个基础固件&#xff1a;BIOS→基本IO系统&#xff0c;它提供以下功能&#xff1a; 上电后自检功能 Power-On Self-Test&#xff0c;即POST&#xff1a;上电后&#xff0c;识别硬件配置并对其进行自检&#xff0c…

预处理详解

目录 预定义符号介绍 ​编辑 预处理指令 #define #define 定义标识符 #define 定义宏 #define 替换规则 #define中#和##的使用 带副作用的宏参数 宏和函数的对比 命令行定义 预处理指令 #undef 预处理指令 #include 头文件被包含的方式&#xff1a; 本地文件包含 …

【LeetCode-139】单词拆分(回溯动归)

目录 题目描述 解法1&#xff1a;记忆回溯 代码实现 解法2&#xff1a;动态规划 代码实现 题目链接 题目描述 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict&#xff0c;判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 说明&#xff1a; 拆分…

Mybatis的一些工具类

** 1.实现了Interceptor接口&#xff0c;并实现了两个拦截方法&#xff1a;update和query。当Mybatis执行update或query语句时&#xff0c;会自动调用intercept法。intercept方法首先获取当前执行的SQL语句&#xff0c;并计算执行该SQL语句所需的时间。然后&#xff0c;它将执行…

【Unity】【VR开发】Unity云同步功能使用心得

【背景】 有时出差,旅行等等也带着电脑,晚上想要继续编辑项目,就需要用到云同步功能。目前实践下来,发现有些内容可以同步,有些内容则是不可以同步的,总结如下。 【如何云同步一个本地项目】 UnityHub的项目面板中有两个选项卡:项目和云端项目。 鼠标挪动到想要云同步…

c++类和对象新手保姆级上手教学(中)

前言&#xff1a; 类和对象中篇&#xff0c;这里讲到的前4个默认成员函数&#xff0c;是类和对象中的重难点&#xff0c;许多资料上的讲法都非常抽象&#xff0c;难以理解&#xff0c;所以我作出这篇总结&#xff0c;分享学习经验&#xff0c;以便日后复习。 目录 6个默认成员…

土壤墒情监测站的工作原理

TH-TS600土壤墒情自动监测站是一种用于自动检测土壤墒情的仪器&#xff0c;它可以实时监测土壤的水分含量和温度&#xff0c;并将数据传输到数据中心或监测中心进行分析和处理。 土壤墒情自动监测站通常由传感器、数据采集器、数据传输设备和数据处理软件等部分组成。传感器是…

Laravel02 路由基本概念和用法 给视图传递请求参数

Laravel02 路由基本概念和用法 1. 路由的基本概念2. 给视图传递请求参数 1. 路由的基本概念 routes文件夹下的web.php是用来定义路由规则的。 自己定义一个路径 2. 给视图传递请求参数 在laravel里使用一个辅助函数request来快速获取请求参数

NX/UG二次开发—CAM—平面铣边界准确设置方法

大家在对平面铣设置边界时&#xff0c;经常遇到边界方向与自己期望的不一致&#xff0c;有些人喜欢用检查刀路是否过切来判断&#xff0c;但是对于倒角、负余量等一些情况&#xff0c;刀路本来就是过切的。对于多边界&#xff0c;可以根据选择的曲线来起点和面的方向来确定&…

Camera2 createCaptureSession源码分析

当应用调用CameraManager#openCamera获取到已打开的camera设备后&#xff0c;会调用createCaptureSession方法来完成camera stream创建和stream的相关配置。在createCaptureSession方法中&#xff0c;首先将应用的surfaces信息封装成可跨binder传递的OutputConfiguration对象&a…

ACE 中的Active Object模式

Active Object 设计模式&#xff1a; 1&#xff09; 根据对象被调用的方式&#xff0c;可以将对象分为两类: Passive Object和Active Object。Passive 和 Object和调用者在同一个线程中&#xff0c;这就是我们通常所用的函数调用。而Active Object和调用在不同的线程中&#xf…

Leo赠书活动-16期 名校毕业生教材

Leo赠书活动-16期 名校毕业生教材 ✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠…

大厂的数据质量中心系统设计

日常工作中&#xff0c;数据开发上线完一个任务后并不是就可以高枕无忧&#xff0c;时常因上游链路数据异常或者自身处理逻辑的 BUG 导致产出的数据结果不可信。而问题发现可经历较长周期&#xff08;尤其离线场景&#xff09;&#xff0c;往往是业务方通过上层数据报表发现数据…

C++中线程的创建

线程创建 引言为什么要使用线程线程的创建使用函数指针示例运行结果使用类对象示例运行结果使用lambda表达式示例运行结果使用带参数的函数作为线程处理函数示例运行结果使用类成员函数示例运行结果引言 在学习C++的过程中,线程的使用作为一个非常重要的部分,也是在复杂项目…

aop实现统一处理日志

使用 AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&#xff09;可以很方便地实现统一处理日志的功能&#xff0c;而不需要修改现有的业务代码。下面是使用 AOP 实现统一处理日志的一般步骤&#xff1a; 定义日志切面&#xff08;Aspect&#xff09;&am…

SpringBoot中日期的格式化处理

目录 1 前言 2 方法 2.1 添加JsonFormat注解 2.2 拓展SpringMVC的消息转化器 2.2.1 编写对象映射器 2.2.2 web层配置类中拓展消息转化器 1 前言 为了符合我们日常的习惯&#xff0c;在对日期类数据进行返回的时候&#xff0c;常常需要对其进行格式化的处理。接下来我将介…

华为---RSTP(二)---RSTP基本配置示例

目录 1. 示例要求 2. 网络拓扑图 3. 配置命令 4. 测试终端连通性 5. RSTP基本配置 5.1 启用STP 5.2 修改生成树协议模式为RSTP 5.3 配置根交换机和次根交换机 5.4 设置边缘端口 6. 指定端口切换为备份端口 7. 测试验证网络 1. 示例要求 为防止网络出现环路&#xf…

【论文精读】MAE

摘要 将掩码重建任务从nlp引入到cv&#xff0c;提出非对称掩码自编码器。 框架 概述 如上图&#xff0c;本文提出掩码自编码器&#xff0c;即将给定原始信号的部分观测值的情况下重建原始信号&#xff0c;编码器将观察到的部分信号(没有掩码标记)映射到潜在表示&#xff0c;采…