518. 零钱兑换 II(力扣LeetCode)

news/2024/4/30 3:15:53/文章来源:https://blog.csdn.net/m0_73841621/article/details/137613606

文章目录

  • 518. 零钱兑换 II
    • 题目描述
    • 动态规划
      • 一维数组
        • 为什么不能交换两个for循环的顺序?
      • 二维数组

518. 零钱兑换 II

题目描述

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

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。

题目数据保证结果符合 32 位带符号整数。

示例 1:

输入:amount = 5, coins = [1, 2, 5]
输出:4
解释:有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

示例 2:

输入:amount = 3, coins = [2]
输出:0
解释:只用面额 2 的硬币不能凑成总金额 3 。

示例 3:

输入:amount = 10, coins = [10]
输出:1

提示:

  • 1 <= coins.length <= 300
  • 1 <= coins[i] <= 5000
  • coins 中的所有值 互不相同
  • 0 <= amount <= 5000

动态规划

一维数组

这段代码是在解决一个称为"零钱兑换 II"的动态规划问题。具体来说,它计算了使用一个无限数量的不同面额硬币凑成某个总金额的所有可能组合的数目。代码使用了C++语言。下面是对这段代码的逐行解释:

// 定义一个Solution类
class Solution {
public:// 定义并实现一个名为change的公共成员函数int change(int amount, vector<int>& coins) {// dp定义了一个整型向量(dp数组),大小为amount + 1,所有值初始化为0vector<int>dp(amount+1, 0);// 将dp数组的第一项设置为1,这表示金额为0的话有1种方式(就是不用任何硬币)dp[0] = 1;// 遍历coins数组,i为索引,从0开始到coins.size() - 1for(int i = 0; i < coins.size(); i++)// 从当前硬币面额coins[i]开始,直到总金额for(int j = coins[i]; j <= amount; j++)// 更新dp[j]的值:dp[j] = dp[j] + dp[j - coins[i]]// 这表示加上用当前的硬币面额coins[i]凑出金额j的新组合数dp[j] += dp[j - coins[i]];// 最后返回dp数组的最后一项,即凑成总金额amount的组合数return dp[amount];}
};

解释一下这个动态规划的核心思想:

  • dp数组的定义:dp[i]表示凑成总金额为i的硬币组合数。
  • 初始化:由于凑成总金额为0的方式只有一种,就是不使用任何硬币,所以初始化dp[0] = 1。
  • 外层循环:遍历每一种硬币。
  • 内层循环:对于每一种硬币,更新金额从硬币面额到总金额的所有dp值。
  • 状态转移方程:dp[j] += dp[j - coins[i]]的含义是,对于每个金额j,考虑当前的硬币面额coins[i],如果我们知道了组成金额j - coins[i]的组合数(即dp[j - coins[i]]),那么就可以通过添加一个coins[i]硬币来得到金额j的一个新的组合。所以,我们要将组成金额j - coins[i]的所有组合数加到dp[j]上。

这个算法的时间复杂度是O(n*m),n是金额amount,m是硬币种类数。空间复杂度是O(n),因为我们使用了一个n + 1大小的dp数组。

为什么不能交换两个for循环的顺序?

在这个特定的动态规划问题中,两个for循环的顺序决定了硬币组合数是如何被计算的,特别是它们影响了状态转移方程的更新方式。如果交换了循环的顺序,将会改变动态规划算法的整个逻辑。

原始顺序(先遍历硬币,然后遍历金额)的循环确保了以下几点:

  1. 组合性:当计算dp[j]时(即凑成金额j的方法数),算法仅考虑使用当前硬币和之前考虑过的硬币的组合。这意味着,对于每个硬币,你都是在累积之前的结果上增加新的可能性。

  2. 无重复:这个顺序确保了在计算组合数时,相同面额的硬币不会被重复计算。即我们不会得到多个考虑顺序不同但实际上相同的硬币组合。

  3. 有序:由于每次循环都是在之前硬币的基础上加上新硬币,因此所有的组合都是以一种有序的方式生成的。

如果交换了for循环的顺序,算法将会改变上述逻辑,导致以下问题:

  • 每次计算dp[j]时,都会考虑所有硬币,这意味着同一金额会被重复计算多次,从而破坏了动态规划的基本原则。
  • 容易出现重复组合,因为对于每个金额,你都在尝试所有的硬币,无法保证硬币使用的唯一顺序,从而可能导致重复的组合方式被计数。
  • 缺乏顺序性,因为你在每个金额的计算中都包含了所有的硬币,这样就会有多种硬币组合顺序产生相同的金额,这些都被错误地算作不同的组合。

因此,保持原始的循环顺序对于解决这个动态规划问题是很重要的,它确保了算法的正确性和效率。

二维数组

这段代码是解决"零钱兑换 II"问题的动态规划解法。下面是对代码的详细注释:

class Solution {
public:int change(int amount, vector<int>& coins) {// 初始化动态规划表格。行数为coins.size()+1,代表0到coins.size个硬币,列数为amount+1,代表0到amount的金额。// dp[i][j]表示使用前i种硬币凑成金额j的方法数。vector<vector<int>> dp(coins.size()+1,vector<int>(amount+1,0));// base case:当金额为0时,即j=0,不使用任何硬币就能凑齐,因此方法数为1。dp[0][0]=1;// 遍历所有的硬币种类for(int i=1;i<=coins.size();i++){// 对于每一种硬币,遍历所有可能的金额for(int j=0;j<=amount;j++){// dp[i][j]首先继承dp[i-1][j]的值,即不使用第i种硬币时凑成金额j的方法数。dp[i][j]=dp[i-1][j];// 如果当前金额j大于等于当前考虑的硬币面额coins[i-1],// 则可以考虑使用这种硬币。此时的方法数为dp[i][j-coins[i-1]],// 加上这种硬币之前的方法数,因为dp[i][j-coins[i-1]]已经计算了使用前i种硬币凑成金额j-coins[i-1]的方法数。if(j>=coins[i-1])dp[i][j]+=dp[i][j-coins[i-1]];}}// 返回使用所有硬币凑成总金额amount的方法数。return dp[coins.size()][amount];}
};

核心思想:

  • 动态规划表dp的大小为(coins.size()+1) * (amount+1)dp[i][j]表示使用前i种硬币(其中硬币种类从0开始编号)凑成金额j的方法数。
  • 初始化dp[0][0]=1表示不使用任何硬币凑成金额0的方法有1种。
  • 外层循环遍历硬币种类,内层循环遍历可能的金额。
  • 对于每一种硬币coins[i-1]和每一个金额j,如果j大于等于当前硬币的面额,我们有两个选择:不使用当前的硬币(继承dp[i-1][j]的值),或者使用当前的硬币(dp[i][j-coins[i-1]]加上当前硬币的数量)。
  • 最终,dp[coins.size()][amount]是使用所有硬币凑成金额amount的方法数。

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

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

相关文章

记录我第一场面了40min+的面试

中冶赛迪信息技术(重庆)有限公司 国企 首先3/24投递的&#xff0c;4/10打了电话问是否接受劳务派遣&#xff0c;我当时不知道劳务派遣什么意思&#xff0c;问了和售前售后是不是类似&#xff0c;得到了不大一样的回答&#xff0c;后面加了微信&#xff0c;定了11开始面试。 这…

【Ubuntu】 Github Readme导入GIF

1.工具安装 我们使用 ffmpeg 软件来完成转换工作1.1 安装命令 sudo add-apt-repository ppa:jonathonf/ffmpeg-3sudo apt-get updatesudo apt-get install ffmpeg1.2 转换命令 &#xff08;1&#xff09;直接转换命令&#xff1a; ffmpeg -i out.mp4 out.gif(2) 带参数命令&…

uos安装lxml避坑记录

环境&#xff1a;紫光电脑uos系统 python&#xff1a;系统自带3.7.3 条件&#xff1a;已打开开发者模式&#xff0c;可以自行安装应用商店之外的软件 一、pip3 install lxml4.8.0可以正正常下载&#xff0c;但出现如下错误 另&#xff1a;为什么是4.8.0&#xff1f;因为这个…

【前缀合】Leetcode 寻找数组的中心下标

题目解析 724. 寻找数组的中心下标 算法讲解 我们使用一个前缀和数组&#xff0c;一个后缀和数组 class Solution { public:int pivotIndex(vector<int>& nums) {// lsum[i] 表⽰&#xff1a;[0, i - 1] 区间所有元素的和// rsum[i] 表⽰&#xff1a;[i 1, n - …

计算机网络----第七天

交换机与路由器 路由器的作用&#xff1a; 作用&#xff1a;寻IP地址 路由转发 隔离广播域 交换和维护路由信息 路由器的特点&#xff1a; 特点&#xff1a;位于网络层 转发流量 实现从源地址到目的地址转发 支持丰富的接口类型 支持多种路由协议 支持数据链路层协议 交换…

机器学习——模型融合:平均法

机器学习——模型融合&#xff1a;平均法 在机器学习领域&#xff0c;模型融合是一种通过结合多个基本模型的预测结果来提高整体模型性能的技术。模型融合技术通常能够降低预测的方差&#xff0c;提高模型的鲁棒性&#xff0c;并在一定程度上提高预测的准确性。本文将重点介绍…

pyside6的QSpinBox自定义特性初步研究(二)

当前的需求是&#xff0c;蓝色背景的画面&#xff0c;需要一个相对应色系的QSpinBox部件。已有的部件风格是这样的&#xff0c;需要新的部件与之般配。 首先新建一个QDoubleSpinBox&#xff0c;并定义其背景色和边框&#xff1a; QDoubleSpinBox { color: white; border:1px…

【精选】发布应用到应用商店的基本介绍

摘要 本文旨在介绍如何在各大应用商店发布应用&#xff0c;包括市场选择、准备材料、上架步骤以及常见被拒原因及解决方法。通过详细的步骤和经验分享&#xff0c;帮助开发者顺利将应用推向市场。 引言 随着移动应用市场的不断发展&#xff0c;越来越多的开发者希望将他们的…

VScode代码查找、替换

VScode代码查找、替换 快捷方法按CtrlF &#xff08;Mac为CommandF&#xff09; 右上角出现的框就是查找框&#xff0c;可以输入想找的内容 点击左边的小尖儿&#xff0c;输入替换的内容后 按回车是替换一个&#xff0c;按Ctrl回车&#xff08;Command回车&#xff09;是全替换…

Vue通过自定义指令实现元素平滑上升的动画效果(可以自定义动画时间、动画效果、动画速度等等)。

1、演示 2、介绍 这个指令不是原生自带的&#xff0c;需要手动去书写&#xff0c;但是这辈子只需要编写这一次就好了&#xff0c;后边可以反复利用。 3、关键API IntersectionObserver IntersectionObserver 是一个用于监测元素是否进入或离开视口&#xff08;viewport&#x…

【Java】Java使用Swing实现一个模拟计算器(有源码)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 今天翻了翻之前写的代码&#xff0c;发现自己之前还写了一个计算器&#xff0c;今天把我之前写的代码分享出来。 我记得那会儿刚学不会写&#xff0c;写的乱七八糟&#xff0c;但拿来当期末作业还是不错的哈哈。 直接上…

学透Spring Boot — 004. Spring Boot Starter机制和自动配置机制

如果你项目中一直用的是 Spring Boot&#xff0c;那么恭喜你没有经历过用 Spring 手动集成其它框架的痛苦。 都说 Spring Boot 大大简化了 Spring 框架开发 Web 应用的难度&#xff0c;这里我们通过配置 Hibernate 的两种方式来深刻体会这一点&#xff1a; 使用 Spring 框架集…

golang的引用和非引用总结

目录 概述 一、基本概念 指针类型&#xff08;Pointer type&#xff09; 非引用类型&#xff08;值类型&#xff09; 引用类型&#xff08;Reference Types&#xff09; 解引用&#xff08;dereference&#xff09; 二、引用类型和非引用类型的区别 三、golang数据类型…

java学习之线程池

java线程池优点&#xff1a; 降低线程创建和销毁的开销&#xff0c;提高系统性能。 提高线程的利用率和系统的吞吐量。 统一线程的管理和监控&#xff0c;避免线程泄漏和线程安全问题。 支持任务队列和拒绝策略等机制&#xff0c;提供灵活的任务调度和任务处理能力。 并不…

String类(1)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

随行付优化外卡收单,助力支付便利化

解决老年人和境外游客在支付过程中遇到的问题和障碍&#xff0c;正逐渐成为整个支付行业的焦点关注词汇。 在有关提高支付服务便利度的意见发布后&#xff0c;有关收单行业的好消息不断涌现&#xff1a;中国银联于3月15日宣布投入30亿元用于升级基础设施&#xff0c;促进支付便…

五一假期来临,各地景区云旅游、慢直播方案设计与平台搭建

一、行业背景 经文化和旅游部数据中心测算&#xff0c;今年清明节假期3天全国国内旅游出游1.19亿人次&#xff0c;按可比口径较2019年同期增长11.5%&#xff1b;国内游客出游花费539.5亿元&#xff0c;较2019年同期增长12.7%。踏青赏花和户外徒步成为假期的热门出游主题。随着…

HarmonyOS 开发-一镜到底“页面转场”动画

介绍 本方案做的是页面点击卡片跳转到详情预览的转场动画效果 效果图预览 使用说明 点击首页卡片跳转到详情页&#xff0c;再点击进入路由页面按钮&#xff0c;进入新的路由页面 实现思路 首页使用了一种视觉上看起来像是组件的转场动画&#xff0c;这种转场动画通常是通过…

09 spring-boot-acurator 定时检测 redis 集群导致 “IOException: Too many open files“

前言 问题的现象主要是如下 项目刚启动的时候 十分正常, 然后 随着时间的推移, 比如说 项目跑了 四五天之后 项目 突然出现问题, 一部分服务能够正常访问, 一部分服务抛出异常 异常信息 就是 too many files 这里的主要的问题是 在异常之前, redis 集群没有密码, 然后 …

Git的简单使用

Git 一&#xff1a;什么是Git&#xff1a; Git是一个分布式版本控制系统&#xff0c;用于跟踪文件的变化并协作开发项目。它允许多个开发者在同一时间内对同一个项目进行编辑&#xff0c;并能够轻松地管理不同版本的文件。Git通过记录文件的变化并创建快照来跟踪项目的历史记…