每日OJ题_完全背包②_力扣322. 零钱兑换

news2024/11/30 8:48:26

目录

力扣322. 零钱兑换

问题解析

解析代码

优化代码(滚动数组)


力扣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

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 2^31 - 1
  • 0 <= amount <= 10^4
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {

    }
};

问题解析

先看能不能将问题转化成我们熟悉的题型。

  • 在一些物品中挑选一些出来,然后在满足某个限定条件下,解决一些问题,大概率是背包模型;
  • 由于每一个物品都是无限多个的,因此是一个完全背包问题。接下来的分析就是基于完全背包的方式来

状态表示: dp[i][j] 表示:从前 i 个硬币中挑选,总和正好等于 j ,所有的选法中,最少的硬币个 数。

状态转移方程:

        线性 dp 状态转移方程分析方式,一般都是根据最后一步的状况,来分情况讨论。但是最后一个物品能选很多个,因此需要分很多情况:

  • 选 0 个第 i 个硬币:此时相当于就是去前 i - 1 个硬币中挑选,总和正好等于 j 。 此时最少的硬币个数为 dp[i - 1][j] 
  • 选 1 个第 i 个硬币:此时相当于就是去前 i - 1 个硬币中挑选,总和正好等于 j - v[i] 。因为挑选了一个 i 硬币,此时最少的硬币个数为 dp[i - 1][j - coins[i]] + 1 ;
  • 选 2 个第 i 个硬币:此时相当于就是去前 i - 1 个硬币中挑选,总和正好等于 j - 2 * coins 。因为挑选了两个 i 硬币,此时最少的硬币个数为 dp[i - 1][j - 2 * coins[i]] + 2 ;
  • ......

综上,状态转移方程为:

dp[i][j]=min(dp[i - 1][j], dp[i - 1][j - coins[i]] + 1, dp[i - 1][j - 2*coins[i]] + 2 ......)

        这时发现,计算一个状态的时候,需要一个循环才能搞定的时候,我们要想到去优化。优化的方向就是用一个或者两个状态来表示这一堆的状态,通常就是用数学的方式做一下等价替换。

        发现第二维是有规律的变化的,因此去看看 dp[i][j - v[i]] 这个状态: dp[i][j - v[i]]=min(dp[i - 1][j - coins[i]] + 1,dp[i - 1][j - 2*coins[i]]] + 2,dp[i - 1] [j - 3*coins[i]] + 3......)

        因此可以修改我们的状态转移方程为: dp[i][j] = min(dp[i - 1][j], dp[i][j - coins[i]] + 1) 。(j >= coins[i] , dp[i][j - coins[i]] 存在 。)(如果初始化多开一行一列,找coins数组要减一)

有个技巧,就是相当于把第二种情况 dp[i - 1][j - coins[i]] + 1 ⾥ ⾯的 i - 1 变成 i 即可。

初始化: dp[0[0]为0,初始化第一行即可。 这里因为取 min ,所以可以把无效的地方设置成无穷大 (0x3f3f3f3f) 因为这里要求正好凑成总和为 j ,因此,需要把第一行除了第一个位置的元素,都设置成无穷大。

填表顺序: 根据状态转移方程,仅需从上往下填表。

返回值: 根据状态表示,返回 dp[n][amount] 。由于最后可能凑不成总数为 amount 的情况,因此返回之前需要特判一下。


解析代码

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        const int INF = 0x3f3f3f3f; // 无穷大的一半
        int n = coins.size();
        vector<vector<int>> dp(n + 1, vector<int>(amount + 1, INF));
        // dp[i][j]表示:从前i个硬币中挑选,总和正好等于j,所有的选法中,最少的硬币个数
        dp[0][0] = 0;
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 0; j <= amount; ++j)
            {
                if(j >= coins[i - 1])
                    dp[i][j] = min(dp[i - 1][j], dp[i][j - coins[i - 1]] + 1);
                else
                    dp[i][j] = dp[i - 1][j];
            }
        }
        return dp[n][amount] >= INF ? -1 : dp[n][amount];
    }
};

优化代码(滚动数组)

背包问题基本上都是利用滚动数组来做空间上的优化:

  1. 利用滚动数组优化。
  2. 直接在原始代码上修改。

在完全背包问题中,优化的结果为:

  1. 仅需删掉所有的横坐标。

(填一行数组的值的时候要用到前面新填的值,所以依旧是从左往右遍历,01背包是从右往左)

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        const int INF = 0x3f3f3f3f; // 无穷大的一半
        int n = coins.size();
        vector<int> dp(amount + 1, INF);
        dp[0] = 0;
        for(int i = 1; i <= n; ++i)
        {
            for(int j = coins[i - 1]; j <= amount; ++j)
            {
                dp[j] = min(dp[j], dp[j - coins[i - 1]] + 1);
            }
        }
        return dp[amount] >= INF ? -1 : dp[amount];
    }
};

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

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

相关文章

密码学 | 椭圆曲线密码学 ECC 入门(一)

目录 正文 1 公共密钥密码学的兴起 2 玩具版 RSA 算法 2.1 RSA 基本原理 2.2 RSA 举例说明 1 加密 2 解密 3 不是完美的陷门函数 ⚠️ 原文地址&#xff1a;A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography ⚠️ 写在前面&#xff1…

【测试开发学习历程】python常用的模块(下)

目录 8、MySQL数据库的操作-pymysql 8.1 连接并操作数据库 9、ini文件的操作-configparser 9.1 模块-configparser 9.2 读取ini文件中的内容 9.3 获取指定建的值 10 json文件操作-json 10.1 json文件的格式或者json数据的格式 10.2 json.load/json.loads 10.3 json.du…

OpenHarmony南向开发案例【智慧中控面板(基于 Bearpi-Micro)】

1 开发环境搭建 【从0开始搭建开发环境】【快速搭建开发环境】 参考鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或复制转到。 【注意】&#xff1a;快速上手教程第六步出拉取代码时需要修改代码仓库地址 在MobaXterm中输入…

ES-全文搜索

模糊查询&#xff1a; 写数据通过id路由到master分片 查询数据到一个节点&#xff0c;该节点会作为一个调度节点判断负载等情况将请求转发到真正节点&#xff08;一般し轮询&#xff09;

【学习笔记十九】EWM Yard Management概述及后台配置

一、EWM Yard堆场管理业务概述 1.Yard Management基本概念 YARD管理针对的是库房以外的区域,可以理解为入大门开始到库门之前的这部分的区域 堆场结构 像在仓库中一样,将相应仓位映射为堆场仓位,可将其分组到堆场分区。场地中可能具有以下结构: 停车位(Park):在堆场中存…

linux(ub)-redis环境部署

1.下载redis包 wget http://download.redis.io/releases/redis-7.0.5.tar.gz 2.解压缩&#xff1a; tar -zxvf redis-7.0.5.tar.gz 3.安装gcc&#xff1a;sudo apt-get install gcc 4. 编译&#xff1a;cd redis-7.0.5 make make make install 5. cd /usr/local/bin/ 6. mkdir …

JAVA基础08- 继承,重写,super以及this

目录 继承&#xff08;extends&#xff09; 定义 说明 作用 方法的重写 定义 重写关键点 方法重写与重载的区别 练习 练习1&#xff08;方法继承与重写的简单练习&#xff09; 练习2&#xff08;方法继承与重写的进阶练习&#xff09; This的使用 定义 作用以及注…

动态代理,XML,Dom4j

文章目录 动态代理概述特点代码实现实现的关键步骤优点 XML概述作用编写第一个XML文件组成声明元素(标签、标记)属性注释转义字符[实体字符字符区(了解) 约束DTD约束Schema约束名称空间 Dom4jXML解析解析方式和解析器解析方式解析器Snipaste_2024-04-17_21-22-44.png<br /&g…

企业linux-堡垒机与跳板机测试案例-6140字详谈

在开始今天内容前&#xff0c;小编先把专栏前面学的Linux命令&#xff08;部分&#xff09;做了思维导图帮助各位平时的学习&#xff1a; 场景&#xff1a; 运维人员管理三台机器&#xff0c;通过远程连接工具连接上三台机器&#xff0c;也知道这三台机器root密码&#xff0c…

Xshell无法输入命令输入命令卡顿

Xshell是一款功能强大的终端模拟软件&#xff0c;可以让用户通过SSH、Telnet、Rlogin、SFTP等协议远程连接到Linux、Unix、Windows等服务器。然而&#xff0c;在使用Xshell的过程中&#xff0c;我们可能会遇到一些问题。比如输入不了命令&#xff0c;或者输入命令很卡。这些问题…

C++笔记:异常

文章目录 C 运行时错误处理机制及其不足之处C 异常概念异常的使用异常的抛出和匹配原则在函数调用链中异常栈展开匹配原则异常的重新抛出举例演示说明例子一&#xff1a;串联举例演示大部分原则例子二&#xff1a;模拟服务器开发中常用的异常继承体系例子三&#xff1a;异常的重…

千锤百炼之每日算法(一)

目录 题外话 正题 第一题 第一题思路 第一题代码详解 第二题 第二题思路 动态规划 解法一 解法一代码详解 解法二 第三题 第三题思路 第三题代码详解 小结 题外话 从今天开始,每天都会更新算法题,一天就三道题 大家最好采用码形结合的方式,也就是代码和图形结合…

最新最全的Jmeter接口测试必会技能:jmeter对图片验证码的处理

jmeter对图片验证码的处理 在web端的登录接口经常会有图片验证码的输入&#xff0c;而且每次登录时图片验证码都是随机的&#xff1b;当通过jmeter做接口登录的时候要对图片验证码进行识别出图片中的字段&#xff0c;然后再登录接口中使用&#xff1b; 通过jmeter对图片验证码…

git出现错误 fail to push some refs to “xxx“

问题产生原因&#xff1a;根据测试猜测造成这一错误的原因是在码云的远程仓库上删除了一个文件,本地没有pull下来,直接进行了commit,commit到本地仓库后,如果在pull下来,也是无法提交的 问题解决办法: 使用 git pull --rebase,拉取远程仓库,并将本地仓库新的提交作为最顶层的提…

C++ 并发编程指南(11)原子操作 | 11.5、内存模型

文章目录 一、C 内存模型1、为什么需要内存模型&#xff1f; 前言 C 11标准中最重要的特性之一&#xff0c;是大多数程序员都不会关注的东西。它并不是新的语法特性&#xff0c;也不是新的类库功能&#xff0c;而是新的多线程感知内存模型。本文介绍的内存模型是指多线程编程方…

(算法版)基于二值图像数字矩阵的距离变换算法

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目展示了欧氏距离、城市街区距离和棋盘距离变换的实现方法。通过定义一个距离变换类&#xff0c;对输入图像进行距离变换操作&#xff0c;并生成对应的距离矩阵。在示例中&#xff0c;展示了在一个480x480的全黑背景图像上设…

GPT国内怎么用?4月最新版本来了

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…

基于SpringBoot+Vue的疾病防控系统设计与实现(源码+文档+包运行)

一.系统概述 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对疾病防控信息管理的提升&a…

20240329-2-树模型集成学习TreeEmbedding

树模型集成学习 集成学习主要有两个思想&#xff0c;分别是bagging和boosting。树模型的集成模型都是使用树作为基模型&#xff0c;最常用的cart树&#xff0c;常见的集成模型有RandomForest、GBDT、Xgboost、Lightgbm、Catboost。 概要介绍 RandomForest 随机森林(Random …

spring的redis注解@Cacheable @Cacheput @CacheEvict的condition、unless

概述 redis的注解使用的过程中总会遇到condition和unless这两个属性&#xff0c;而且不同的注解使用注意事项不一样。本人也是错误使用之后详细查询了一下&#xff0c;作了如下的总结。 Cacheale 这个注解的使用和意义这里不多说&#xff0c;可以查看我的其他文档。这里主要说…