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

LeetCode322. 零钱兑换

322. 零钱兑换

文章目录

    • [322. 零钱兑换](https://leetcode.cn/problems/coin-change/)
      • 一、题目
      • 二、题解
        • 方法一:完全背包二维数组
        • 方法二:一维数组
      • 三、注意


一、题目

给你一个整数数组 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

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104

二、题解

方法一:完全背包二维数组

这个问题可以看作是一个完全背包问题的变形,即每种硬币的数量是无限的,而不是有限的。

  • 算法思路:

    • 首先,我们要定义一个二维数组 dp ,其中 dp[i][j] 表示用前 i+1 种硬币(即 coins[0]coins[i])凑成金额 j 所需的最少硬币个数。

    • 然后,我们要初始化 dp 数组,对于第一种硬币 coins[0] ,我们只需要看金额 j 是否能被它整除,如果能,那么 dp[0][j] = j / coins[0] ,否则 dp[0][j] = INT_MAX (表示无法凑成)。

    • 接下来,我们要逐行更新 dp 数组,对于第 i+1 种硬币 coins[i] ,我们有两种选择:使用它或者不使用它。如果不使用它,那么 dp[i][j] = dp[i-1][j] ,即和前 i 种硬币的结果一样;如果使用它,那么我们要保证金额 j 大于等于硬币面额 coins[i] ,并且减去这个面额后的金额能够被前 i+1 种硬币凑成,即 dp[i][j-coins[i]] != INT_MAX ,那么 dp[i][j] = dp[i][j-coins[i]] + 1 ,即在减去这个面额后的结果上加一。我们要在这两种选择中取最小值,即 dp[i][j] = min(dp[i-1][j], dp[i][j-coins[i]] + 1)

    • 最后,我们要返回 dp[coins.size() - 1][amount] ,即用所有种类的硬币凑成总金额所需的最少硬币个数。如果这个值等于 INT_MAX ,说明无法凑成,返回 -1 ;否则返回这个值。

  • 具体实现:

    • 可以用一个嵌套的循环来实现上述算法思路,外层循环遍历硬币种类,内层循环遍历金额。每次更新 dp[i][j] 时,先赋值为不使用当前硬币的结果,然后判断是否可以使用当前硬币,并更新为最小值。

    • 我们还需要注意一些边界情况,比如当金额为零时,返回零;当硬币数组为空时,返回 -1

    class Solution {
    public:int coinChange(vector<int>& coins, int amount) {if (amount == 0) return 0;vector<vector<int>> dp(coins.size(), vector<int>(amount + 1, INT_MAX));// 初始化for (int i = 0; i <= amount; i++) {if (i % coins[0] == 0) {dp[0][i] = i / coins[0];}}for (int i = 1; i < coins.size(); i++) {for (int j = 0; j <= amount; j++) {dp[i][j] = dp[i - 1][j];if (j >= coins[i] && dp[i][j - coins[i]]!=INT_MAX) {dp[i][j] = min(dp[i][j], dp[i][j - coins[i]] + 1);}}}return dp[coins.size() - 1][amount] == INT_MAX? -1 : dp[coins.size() - 1][amount];}
    };
    
  • 算法分析:

    • 时间复杂度:O(N*M),其中 N 是硬币种类数,M 是总金额。我们需要遍历所有的硬币和金额组合,每次更新一个状态值。

    • 空间复杂度:O(N*M),其中 N 是硬币种类数,M 是总金额。需要一个二维数组来存储所有的状态值。

方法二:一维数组

算法思路和具体实现和上面的二维数组差不多,不过我也copy了一下~

  • 算法思路:

    • 首先,我们定义一个一维数组 dp ,其中 dp[j] 表示凑成金额 j 所需的最少硬币个数。
    • 然后,我们初始化 dp 数组,对于金额为零的情况,我们不需要任何硬币,所以 dp[0] = 0 。对于其他金额,我们先设为一个很大的数,比如 INT_MAX ,表示无法凑成。
    • 接下来,我们遍历每种硬币 coins[i] ,对于每种硬币,我们从小到大遍历金额 j ,如果 j >= coins[i] ,说明我们可以用这种硬币来凑成金额 j ,那么我们就比较使用这种硬币和不使用这种硬币的结果,取最小值,即 dp[j] = min(dp[j], dp[j - coins[i]] + 1) 。注意这里和 01 背包问题的区别,01 背包问题中只能用一次每种物品,所以要从大到小遍历金额,避免重复使用;而完全背包问题中可以用无限次每种物品,所以要从小到大遍历金额,允许重复使用。
    • 最后,我们返回 dp[amount] ,即凑成总金额所需的最少硬币个数。如果这个值等于 INT_MAX ,说明无法凑成,返回 -1 ;否则返回这个值。
  • 具体实现:

    • 这个代码和上一个代码的区别在于,它只用了一个一维数组来存储状态值,而不是一个二维数组。这样做的原因是,对于每种硬币,我们只需要知道上一行的状态值就可以更新当前行的状态值,所以我们可以用一个一维数组来代替二维数组,节省空间。
    • 我们可以用一个嵌套的循环来实现上述算法思路,外层循环遍历硬币种类,内层循环遍历金额。每次更新 dp[j] 时,先判断是否可以使用当前硬币,并更新为最小值。
    • 我们还需要注意一些边界情况,比如当金额为零时,返回零;当硬币数组为空时,返回 -1
    class Solution {
    public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX);dp[0] = 0;for (int i = 0; i < coins.size(); i++) {for (int j = 0; j <= amount; j++) {if (j >= coins[i] && dp[j - coins[i]]!=INT_MAX) {dp[j] = min(dp[j], dp[j - coins[i]] + 1);}}}return dp[amount] == INT_MAX? -1 : dp[amount];}
    };
    
  • 算法分析:

    • 时间复杂度:O(N*M),其中 N 是硬币种类数,M 是总金额。我们需要遍历所有的硬币和金额组合,每次更新一个状态值。
    • 空间复杂度:O(M),其中 M 是总金额。我们只需要一个一维数组来存储状态值。

三、注意

这道题不在乎硬币是排列还是组合,是因为我们只关心最少的硬币个数,而不关心硬币的顺序。换句话说,我们只要找到一种硬币组合,使得它的总金额等于目标金额,并且硬币个数最少,那么这种组合就是最优解,无论它的硬币顺序如何。例如,如果目标金额是 11 ,硬币面额是 [1, 2, 5] ,那么无论是 [5, 5, 1] 还是 [1, 5, 5] ,都是最优解,因为它们都只用了 3 个硬币。所以,不需要考虑排列和组合的区别,只需要考虑状态转移的逻辑。

相关文章:

LeetCode322. 零钱兑换

322. 零钱兑换 文章目录 [322. 零钱兑换](https://leetcode.cn/problems/coin-change/)一、题目二、题解方法一&#xff1a;完全背包二维数组方法二&#xff1a;一维数组 三、注意 一、题目 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 a…...

AUTOSAR扫盲贴--不是黑神话【基本概念和方法论】

猴子纵有72搬变化,也跳不出如来的手掌 目录 1. 引言 2. AUTOSAR的基本概念 2.1. AUTOSAR的架构和组成部分 2.2. AUTOSAR的规范和...

python抠图(去水印)开源库lama-cleaner入门应用实践

1. 关于 Lama Cleaner Lama Cleaner 是由 SOTA AI 模型提供支持的免费开源图像修复工具。可以从图片中移除任何不需要的物体、缺陷和人&#xff0c;或者擦除并替换&#xff08;powered by stable diffusion&#xff09;图片上的任何东西。 特征&#xff1a; 完全免费开源&am…...

Nginx可视化管理工具结合cpolar实现远程访问内网服务

前言 Nginx Proxy Manager 是一个开源的反向代理工具&#xff0c;不需要了解太多 Nginx 或 Letsencrypt 的相关知识&#xff0c;即可快速将你的服务暴露到外部环境&#xff0c;并且支持 SSL 配置。基于 Tabler 的美观且安全的管理界面,无需了解 Nginx 即可轻松创建转发域、重定…...

CCC数字钥匙设计【BLE】 --建立安全测距

1、建立安全测距Establish Secure Ranging 车端总共有三种建立安全测距的方式&#xff0c;具体如下&#xff1a; 1) Optimal Flow 2) Sub-Optimal Flow 3) Ranging Recovery Flow 为了确定建立安全测距需要执行哪条流程&#xff0c;车辆需要进行以下流程选择。当车辆和设备…...

Ubuntu22.04 Opencv4.5.1 CPU和GPU编译攻略,Opencv CPU和GPU编译保姆教程 亲自测试。

1、安装opencv依赖 安装时最好更换一下源。 sudo apt-get -y update sudo apt-get -y install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-get -y install libgtk-3-dev gfortran openexr libatlas-base-dev python3-dev pyt…...

常识判断 --- 党史

目录 中共1~3大 例题 国民党 例题 中共4~5大 例题 中共起义~会议 例题 中共六届六中全会&#xff08;1938年9月&#xff09; 中共七大&#xff08;1945年4月&#xff09; 例题 中共七届二中全会 例题 中共8~10大 中共11~12届全会 例题 中共13~14大 …...

Rust 基础再理解

Rust堆栈 Rust中各种类型的值默认都存储在栈中&#xff0c;除非显式地使用Box::new()将它们存放在堆上&#xff0c;但数据要存放在栈中&#xff0c;要求其数据类型的大小已知。对于静态大小的类型&#xff0c;可直接存储在栈上&#xff0c;如裸指针、布尔、字符、整数浮点数&a…...

Opencv cuda版本在ubuntu22.04中安装办法,解决Could NOT find CUDNN的办法

文章目录 概要下载cuda的runfile版本配置环境变量官网下载cudann安装Opencv依赖包下载opencv和opencv_contrib并解压准备编译安装anaconda环境执行编译命令安装OpenCV并检查是否安装成功 概要 解决以下安装问题&#xff1a; -- Could NOT find CUDNN: Found unsuitable versi…...

全网首发YOLOv8暴力涨点:Gold-YOLO,遥遥领先,超越所有YOLO | 华为诺亚NeurIPS23

💡💡💡本文独家改进:提出了全新的信息聚集-分发(Gather-and-Distribute Mechanism)GD机制,Gold-YOLO,替换yolov8 head部分 实现暴力涨点 Gold-YOLO | 亲测在多个数据集能够实现大幅涨点 💡💡💡Yolov8魔术师,独家首发创新(原创),适用于Yolov5、Yolov7、…...

BD就业复习第四天

1. 布隆过滤器怎么实现去重 布隆过滤器是一种用于快速检查一个元素是否可能存在于一个大集合中的数据结构&#xff0c;但它并不适用于精确去重。因为布隆过滤器具有一定的误判率&#xff08;可能会将不存在的元素误判为存在&#xff09;&#xff0c;所以不能确保完全的去重。但…...

数据结构 | 树

树 树是n&#xff08;n>0&#xff09;个结点的有限集。当n 0时&#xff0c;称为空树。在任意一棵非空树中应满足&#xff1a; 有且仅有一个特定的称为根的结点。当n>1时&#xff0c;其余节点可分为m&#xff08;m>0&#xff09;个互不相交的有限集T1,T2,…,Tm&#…...

Android11 适配

一、修改targetSdkVersion为30 将build.gradle的目标版本targetSdkVersion修改为30&#xff08;Android 11&#xff09; targetSdkVersion 30Android11的改变改变主要影响以Adnroid11 为目标版本的应用&#xff08;targetSdkVersion>30才有影响&#xff09;&#xff0c;和所…...

UML基础与应用之对象图

什么是对象图&#xff1f; 对象图表示一组对象及它们之间的关系&#xff0c;是某一时刻系统详细信息的快照&#xff0c;描述系统交互的静态图形&#xff0c;它由协作的对象组成&#xff0c;但不包含在对象之间传递的任何消息。因为对象是类的实例化&#xff0c;所以说某一时刻…...

英码科技精彩亮相火爆的IOTE 2023,多面赋能AIoT产业发展!

9月20日至22日&#xff0c;在这金秋飒爽的季节&#xff0c;为期三天的IOTE 2023第二十届国际物联网展深圳站在深圳国际会展中心盛大举行。英码科技精彩亮相本届展会&#xff0c;并在同期举办的AIoT视觉物联产业生态大会发表了主题演讲&#xff0c;与生态伙伴们共同探讨AIoT产业…...

400G QSFP-DD FR4 与 400G QSFP-DD FR8光模块:哪个更适合您的网络需求?

QSFP-DD 光模块随着光通信市场规模的不断增长已成为400G市场中客户需求量最高的产品。其中400G QSFP-DD FR4和400G QSFP-DD FR8光模块都是针对波分中距离传输&#xff08;2km&#xff09;的解决方案&#xff0c;它们之间有什么不同&#xff1f;应该如何选择应用&#xff1f;飞速…...

【Android】Kotlin 中的 apply、let、with、also、run 到底有啥区别?

一、图示 二、apply apply 函数接收一个对象并返回该对象本身。它允许您在对象上执行一些操作&#xff0c;同时仍然返回原始对象。 这个函数的语法为&#xff1a; fun <T> T.apply(block: T.() -> Unit): T 其中&#xff0c;T 是对象的类型&#xff0c;block 是一…...

设计模式——职责链模式

职责链模式 职责链模式职责链模式解决什么问题&#xff1f;职责链模式实现 职责链模式 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这个对象练成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;知道有一个对象处理它为止 …...

小程序自定义tabbar,中间凸起

微信小程序自带tabbar&#xff0c;但无法实现中间按钮凸起样式和功能&#xff0c;因此按照设计重新自定义一个tabbar 1、创建tabbar文件&#xff0c;与pages同级创建一个文件夹&#xff0c;custom-tab-bar,里面按照设计图将底部tabbar样式编写 <view class"tab-bar&q…...

数据结构-顺序栈C++示例

栈(stack)是限定仅在表尾进行插入或删除操作的线性表。 对栈来说&#xff0c;表尾端称为栈顶(top)&#xff0c; 表头端称为栈底(bottom)&#xff0c;不含元素的空表称为空栈。 假设栈 S ( a 1 , a 2 , a 3 , ⋯ , a n ) S(a_1,a_2,a_3,\cdots,a_n) S(a1​,a2​,a3​,⋯,an​…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...