当前位置: 首页 > news >正文

备战秋招60天算法挑战,Day34

题目链接: https://leetcode.cn/problems/coin-change/

视频题解: https://www.bilibili.com/video/BV1qsvDeHEkg/

LeetCode 322.零钱兑换

题目描述

给你一个整数数组coins,表示不同面额的硬币;以及一个整数amount,表示总金额。

计算并返回可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回-1

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

举个例子:

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

视频题解

零钱兑换

思路来源

思路来源

知识回顾

动态规划是一种通过将原问题分解为子问题来求解复杂问题的算法思想。它通常用于求解最优化问题,例如最长公共子序列、背包问题等。动态规划的核心思想是将原问题分解为若干个子问题,通过求解子问题的最优解推导出原问题的最优解。可以通过两点来判断一个问题能不能通过动态规划来解,一是该问题是否存在递归结构,二是对应的子问题能否记忆化。动态规划可以通过带备忘录的自上而下的递归自下而上的迭代来分别实现。由于递归需要用到栈来实现,一些语言对递归的深度是有限制的,所以自下而上的迭代是动态规划的最佳实现方式

思路解析

根据题意,零钱兑换的决策树如下图:

根节点表示要兑换的总金额amount,每个子节点表示amount已经兑换了coins[i](对于图中的例子0 <= i < 3)以后剩余要兑换的钱。叶子结点为0表示从根节点到叶子结点这条兑换路径是行得通的,叶子结点为负数表示行不通。

实际上本题就是要求在这棵树上所有行得通的兑换路径中,寻找最短合法路径的长度

整个决策树存在递归结构,还存在重复子问题两个节点2三个节点1,这些子问题计算一次后可以直接保存下来,避免多次重复计算。这就满足了使用动态规划的条件:存在递归结构子问题可以记忆化。所以本题可以用动态规划来解。动态规划可以通过带备忘录的自上而下的递归自下而上的迭代来分别实现。

方法一 自上而下的递归+备忘录

本题单纯的使用递归会超时的。

通过观察上图,可以看出每个分支存在很多相同的子问题,比如兑换总金额2元,兑换总金额1元。我们可以在递归的过程中使用备忘录把这些子问题的结果保存起来,后面就作为跳出递归的一个条件,这样可以大大节约时间。

C++代码

class Solution {
public:int coinChange(vector<int> &coins, int amount) {//定义备忘录vector<int> count(amount + 1, INT_MAX);count[0] = 0;int res = help(coins, count, amount);return res;
}int help(vector<int> &coins, vector<int>& count, int amount) {//如果备忘录中已经保存结果if (count[amount] < INT_MAX - 1) {//直接返回return count[amount];}int coins_len = coins.size();int min_res = INT_MAX;for (int i = 0; i < coins_len; ++i) {if (amount - coins[i] >= 0) {//递归遍历(DFS)所以的可能性int res = help(coins, count, amount - coins[i]);if (res >= 0 && res < min_res) {min_res = res + 1;}}}//更新备忘录count[amount] = min_res == INT_MAX ? -1 : min_res;//返回结果return count[amount];
}};

java代码

class Solution {public int coinChange(int[] coins, int amount) {// 定义备忘录int[] count = new int[amount + 1];Arrays.fill(count, Integer.MAX_VALUE);count[0] = 0;int res = help(coins, count, amount);return res;}private int help(int[] coins, int[] count, int amount) {// 如果备忘录中已经保存结果if (count[amount] < Integer.MAX_VALUE - 1) {// 直接返回return count[amount];}int min_res = Integer.MAX_VALUE;for (int coin : coins) {if (amount - coin >= 0) {// 递归遍历(DFS)所有的可能性int res = help(coins, count, amount - coin);if (res >= 0 && res < min_res) {min_res = res + 1;}}}// 更新备忘录count[amount] = (min_res == Integer.MAX_VALUE) ? -1 : min_res;// 返回结果return count[amount];}
}

python代码

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:# 定义备忘录count = [float('inf')] * (amount + 1)count[0] = 0res = self.help(coins, count, amount)return resdef help(self, coins, count, amount):# 如果备忘录中已经保存结果if count[amount] < float('inf') - 1:# 直接返回return count[amount]min_res = float('inf')for coin in coins:if amount - coin >= 0:# 递归遍历(DFS)所有的可能性res = self.help(coins, count, amount - coin)if res >= 0 and res < min_res:min_res = res + 1# 更新备忘录count[amount] = -1 if min_res == float('inf') else min_res# 返回结果return count[amount]

复杂度分析

时间复杂度: 时间复杂度为O(mn),其中mcoins中元素的个数,n为要兑换的总金额。

空间复杂度: 空间复杂度为O(n)n为要兑换的总金额。

方法二 自下而上的迭代

实现自下而上而上迭代的两个关键步骤:确定状态转移公式边界情况

首先定义dp[i]表示兑换金额为i,使用coins中的零钱兑换所需最少的个数。dp[i]的准确定义是状态转移公式成功推导的关键。

针对coins = [1, 2, 5]amount = 4。从上面的决策树可以看出可以把兑换4块钱分解成兑换3元,兑换2元,兑换-1元,三个子问题。其中-1元是无法兑换的,可以直接把这个分支剪掉。可以得到下面的公式:

dp[4] = min{dp[3], dp[2]} + 1

类似地,把amount = 4扩展到amount = n,可以得到如下状态转移公式

dp[n] = min{dp[n-coins[0]], dp[n-coins[1]], ..., dp[n-coins[m-1]]} + 1

其中mcoins的大小,且需要n - coins[i] >= 00 <= i < m​。

接下来看一下边界情况,题目中已经说明amount = 0时对应的兑换个数为0,所以dp[0] = 0

C++代码

class Solution {
public:int coinChange(vector<int> &coins, int amount) {int coins_len = coins.size();//因为dp是从0开始,要兑换总金额为amount,所以要申请amount+1个元素vector<int> dp(amount + 1, amount + 1);//边界处理dp[0] = 0;for (int i = 1; i <= amount; ++i) {for (int j = 0; j < coins_len; ++j) {//剪掉节点为负的情况if (i - coins[j] >= 0) {//状态转移公式dp[i] = min(dp[i], dp[i-coins[j]] + 1);}}}return dp[amount] == amount + 1 ? -1: dp[amount];}
};

java代码

class Solution {public int coinChange(int[] coins, int amount) {int coins_len = coins.length;// 因为dp是从0开始,要兑换总金额为amount,所以要申请amount+1个元素int[] dp = new int[amount + 1];Arrays.fill(dp, amount + 1);// 边界处理dp[0] = 0;for (int i = 1; i <= amount; i++) {for (int j = 0; j < coins_len; j++) {// 剪掉节点为负的情况if (i - coins[j] >= 0) {// 状态转移公式dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);}}}return dp[amount] == amount + 1 ? -1 : dp[amount];}
}

python代码

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:coins_len = len(coins)# 因为dp是从0开始,要兑换总金额为amount,所以要申请amount+1个元素dp = [amount + 1] * (amount + 1)# 边界处理dp[0] = 0for i in range(1, amount + 1):for j in range(coins_len):# 剪掉节点为负的情况if i - coins[j] >= 0:# 状态转移公式dp[i] = min(dp[i], dp[i - coins[j]] + 1)return -1 if dp[amount] == amount + 1 else dp[amount]

复杂度分析

时间复杂度: 时间复杂度为O(m*n),其中mcoins中元素的个数,n为要兑换的总金额。

空间复杂度: 空间复杂度为O(n)n为要兑换的总金额。

相关文章:

备战秋招60天算法挑战,Day34

题目链接&#xff1a; https://leetcode.cn/problems/coin-change/ 视频题解&#xff1a; https://www.bilibili.com/video/BV1qsvDeHEkg/ LeetCode 322.零钱兑换 题目描述 给你一个整数数组coins&#xff0c;表示不同面额的硬币&#xff1b;以及一个整数amount&#xff0c;表…...

vue实现评论滚动效果

vue插件实现滚动效果 一、安装组件 官网地址&#xff1a;https://chenxuan0000.github.io/vue-seamless-scroll/ 1、vue2安装 npm install vue-seamless-scroll --savevue3安装 npm install vue3-seamless-scroll --save二、组件引入 <template><div v-if"…...

iphone13 不升级IOS使用广电卡

iPhone13的信号&#x1f4f6;&#xff0c;15系统刷高版本iPCC&#xff0c;本帖以后不再更新&#xff01;&#xff01;&#xff01; 自从知道可以通过刷iPCC的方式改善信号(不更新iOS大版本的情况下)&#xff0c;尝试了各种版本。 我自己用下来总结 - 移动联通48、49、50 &…...

网络地址转换

文章目录 1. NAT使用环境2. NAT的优缺点3. NAT的三种类型4. NAT工作原理5. 配置示例6. 常用排错命令 1. NAT使用环境 需要连接到互联网&#xff0c;但主机没有全局唯一的IP地址&#xff1b;更换的ISP的要求对网络进行重新编址&#xff1b;需要合并两个使用相同编址方案的内联网…...

【python】 @property属性详解 and mysql的sqlalchemy的原生sql

【python】 property属性详解 一文搞懂python中常用的装饰器&#xff08;classmethod、property、staticmethod、abstractmethod…&#xff09; sqlalchemy的原生sql from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker# 数据库连接字符串 DATAB…...

西门子WinCC开发笔记(一):winCC西门子组态软件介绍、安装

文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/142060535 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…...

如何在5个步骤中编写更好的ChatGPT提示

ChatGPT是一个风靡全球的生成式人工智能 (AI) 工具。虽然它有可能编造一些东西&#xff0c;但是通过精心设计提示&#xff0c;可以确保获得最佳结果。在这篇文章中&#xff0c;我们将探讨如何做到这一点。 在本文中&#xff0c;我将向你展示如何编写提示&#xff0c;激励驱动C…...

最小堆最大堆

文章目录 最小堆、最大堆最小堆&#xff08;Min-Heap&#xff09;最大堆&#xff08;Max-Heap&#xff09;堆的主要操作及时间复杂度堆的常见应用堆的数组表示大根堆--堆排序 最小堆、最大堆 最小堆&#xff08;Min-Heap&#xff09;和最大堆&#xff08;Max-Heap&#xff09;…...

华为 HCIP-Datacom H12-821 题库 (10)

有需要题库的可以看主页置顶 V群进行学习交流 1.缺省情况下&#xff0c;BGP 对等体邻接关系的保持时间是多少秒&#xff1f; A、120 秒 B、60 秒 C、10 秒 D、180 秒 答案&#xff1a;D 解析&#xff1a; BGP 存活消息每隔 60 秒发一次&#xff0c;保持时间“180 秒” 2.缺省…...

如何利用命令模式实现一个手游后端架构?

命令模式的原理解读 命令模式的英文翻译是 Command Design Pattern。在 GoF 的《设计模式》一书中&#xff0c;它是这么定义的&#xff1a; The command pattern encapsulates a request as an object, thereby letting us parameterize other objects with different reques…...

ThreadLocal 释放的方式有哪些

ThreadLocal基础概念&#xff1a;IT-BLOG-CN ThreadLocal是Java中用于在同一个线程中存储和隔离变量的一种机制。通常情况下&#xff0c;我们使用ThreadLocal来存储线程独有的变量&#xff0c;并在任务完成后通过remove方法清理这些变量&#xff0c;以防止内存泄漏。然而&…...

监控-zabbix

1运维监控 是指对计算机系统、网络、服务器等关键IT基础设施进行实时监控&#xff0c;以确保系统的稳定运行和及时发现潜在问题 2老监控框架&#xff08;不会用但需要知道&#xff09; Cacti&#xff1a; Cacti是一款基于PHP、MySQL开发的网络流量监测图形分析工具。主要监…...

设计模式 解释器模式(Interpreter Pattern)

文章目录 解释器模式简绍解释器模式的结构优缺点UML图具体代码实现Context 数据实体类&#xff0c;可以包含一些方法Abstract Expression 创建接口方法Terminal Expression 对数据简单处理Non-Terminal Expression 同样实现抽象接口方法Client&#xff08;客户端&#xff09; 调…...

Linux echo命令讲解及与重定向符搭配使用方法,tail命令及日志监听方式详解

echo echo具有回声&#xff0c;回响的意思&#xff0c;在linux系统中echo一般可以输出指定字符或用于命令执行 echo命令的用法为 echo 输出字符串 或 echo 命令 若参数为字符串则进行字符串输出&#xff0c;注意若字符串中含空格最好将其用引号括起&#xff0c;防止echo命…...

Linux网络:总结协议拓展

1. TCP/IP四层模型总结 2. 网络协议拓展 DNS协议&#xff08;地址解析协议&#xff09; TCP/IP使用IP地址和端口号来确定网络中一台主机的一个程序。 但是这样标定不方便记忆&#xff0c;于是开始引出主机名&#xff08;字符串&#xff09;&#xff0c;使用hosts文件来描述…...

去除恢复出厂设置中UI文字显示

文章目录 需求场景 一、代码跟踪与分析在线文字搜索RK平台本地源码搜索实际测试验证代码推理 二、实现方案三、延伸知识四、知识总结 需求 需求&#xff1a;去除恢复出厂设置中UI文字显示 场景 Android 相关产品各种方向旋转、强制横竖屏等需求&#xff0c;导致在恢复出厂设…...

《高校教育管理》

《高校教育管理》为中文社会科学引文索引&#xff08;CSSCI&#xff09;来源期刊、北大中文核心期刊、RCCSE中国核心学术期刊、人大“复印报刊资料”重要转载来源期刊&#xff0c;是江苏大学主办&#xff0c;中国高等教育管理研究会协办的全国性高等教育管理专业期刊。 ISSN 1…...

全国计算机二级考试C语言篇4——选择题

运算符与表达式 1.赋值的正确写法 赋值操作是一个很常见的操作&#xff0c;但是赋值操作也有一些需要注意的地方。赋值操作是将一个表达式的值赋给一个变量的过程。在C语言中&#xff0c;赋值操作符是""。结合性从右到左&#xff0c;不控制求值顺序。 下面是几种C语言…...

数据结构————哈希表

哈希表&#xff08;Hash table&#xff09;&#xff0c;也被称为散列表&#xff0c;是一种根据关键值&#xff08;Key value&#xff09;而直接进行访问的数据结构。它通过把关键值映射到表中的一个位置来访问记录&#xff0c;从而加快查找的速度。这个映射函数被称为散列函数或…...

element select + tree

element select tree的使用 <template slot"action1" slot-scope"text, record, index"><el-select v-model"record.tagValue" multiple placeholder"请选择":filter-method"(e) > filterTree(e, index)" filt…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...