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

力扣热题100-----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] <= 231 - 1
0 <= amount <= 104

动态规划思路

1.状态定义
定义nums[i]为凑成金额i所需的最少硬币数量。

2.状态初始化

nums[0] = 0:凑成金额0不需要任何硬币。

• 对于其他金额i,初始值设为amount + 1。这是一个足够大的数,表示初始时无法凑成这些金额。

3.状态转移方程
对于每个金额i(从1amount),尝试使用每种硬币coin

• 如果当前金额i大于等于硬币面额coin,则可以考虑使用这个硬币。

• 更新nums[i]的值为:
[
nums[i]=\min(nums[i],nums[i-coin]+1)
]
这里的nums[i - coin] + 1表示在凑成金额i - coin的基础上,再加一个面额为coin的硬币。

4.最终结果

• 如果nums[amount]仍然是初始值amount + 1,说明无法凑成该金额,返回-1

• 否则,返回nums[amount],即凑成金额amount所需的最少硬币数量。

class Solution {public int coinChange(int[] coins, int amount) {int[]   nums=new int[amount+1];for(int i=0;i<=amount;i++){nums[i]=amount+1;}nums[0]=0;for(int i=1;i<=amount;i++){for(int coin:coins){if(i>=coin){nums[i]=Math.min(nums[i],nums[i-coin]+1);}}}return nums[amount]==amount+1 ? -1:nums[amount];}
}

动态规划法:

动态规划法介绍:

动态规划(Dynamic Programming,简称 DP)是一种用于解决多阶段决策问题的算法思想,它通过将复杂问题分解为更简单的子问题,并存储这些子问题的解以避免重复计算,从而高效地解决问题。动态规划通常用于优化问题,尤其是那些具有重叠子问题和最优子结构特性的问题。

核心概念

• 最优子结构:

• 一个问题的最优解可以由其子问题的最优解组合而成。换句话说,问题的解可以分解为若干个子问题的解。

• 例如,在爬楼梯问题中,到达第(n)阶的方法数可以由到达第(n-1)阶和第(n-2)阶的方法数组合而成。

• 重叠子问题:

• 在递归求解过程中,同一个子问题会被多次计算。动态规划通过存储这些子问题的解(通常使用一个数组或哈希表),避免重复计算,从而提高效率。

• 例如,在递归计算斐波那契数列时,会多次计算相同的值,而动态规划通过存储这些值来避免重复计算。

动态规划的优势
• 高效性:

• 动态规划通过存储子问题的解,避免了重复计算,大大提高了算法的效率。时间复杂度通常为(O(n))。

• 适用性:

• 动态规划适用于具有重叠子问题和最优子结构特性的问题,如背包问题、最长公共子序列、最短路径问题等。

• 可扩展性:

• 动态规划的思想可以扩展到多维问题,通过增加状态维度来解决更复杂的问题。

动态规划的局限性
• 空间复杂度:

• 动态规划通常需要额外的空间来存储子问题的解,空间复杂度可能较高。例如,爬楼梯问题的空间复杂度为(O(n))。

• 状态转移方程的推导:

• 动态规划的关键在于推导状态转移方程,这需要对问题有深入的理解和分析。

• 适用范围:

• 动态规划只适用于具有重叠子问题和最优子结构特性的问题,对于不符合这些特性的问题,动态规划可能不适用。

总结

动态规划是一种强大的算法思想,通过将复杂问题分解为更简单的子问题,并存储这些子问题的解,避免重复计算,从而高效地解决问题。爬楼梯问题是动态规划的经典应用之一,通过定义状态、初始化状态、状态转移和计算顺序,可以高效地求解问题。

http://www.xdnf.cn/news/1283743.html

相关文章:

  • 使用docker compose 部署dockge
  • scikit-learn/sklearn学习|岭回归解读
  • Mybatis学习之逆向工程(十)
  • Python 类元编程(类工厂函数)
  • Vue 3 快速入门 第六章
  • 【MATLAB 2025a】安装离线帮助文档
  • web前端第三次作业
  • Azimutt:一款免费开源的多功能数据库工具
  • Linux下安装jdk
  • C语言(06)——二、八、十、十六进制的相互转换
  • 机器学习 TF-IDF提取关键词,从原理到实践的文本特征提取利器​
  • 稠密检索:基于神经嵌入的高效语义搜索范式
  • 【CSS 布局】告别繁琐计算:CSS 现代布局技巧(gap, aspect-ratio, minmax)
  • Wed前端第二次作业
  • 【Node.js从 0 到 1:入门实战与项目驱动】1.4 Node.js 的发展与生态(历史版本、LTS 版本、npm 生态系统)
  • 【LeetCode 热题 100】(七)链表
  • 5G NR NTN 在 PHY 层和 MAC 层实现 OAI
  • 软考 系统架构设计师系列知识点之杂项集萃(121)
  • 深入解析Windows系统下UDP绑定失败的原理与系统级解决方案
  • SQL中BETWEEN与IN的差异详解
  • ERA5---MATLAB处理水汽数据与臭氧数据的读取与重采样-重复性工作
  • Linux系统编程Day12 -- 环境变量(初识)
  • Flutter学习笔记(六)---状态管理、事件、路由、动画
  • MCU 软件断点注意事项!!!
  • LVPECL、LVDS、LVTTL、LVCMOS四种逻辑电平标准的全面对比
  • C# 异步编程(BeginInvoke和EndInvoke)
  • GPT-5 全面解析与最佳实践指南
  • python面向对象设计模式
  • Linux DNS服务解析原理与搭建
  • OrbStack 入门教程:macOS 上的轻量级容器与虚拟机管理工具