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

LeetCode刷题记录----322.零钱兑换(Medium)

2025/9/21

题目(Medium):

322.零钱兑换


我的思路:

模式识别:要凑到11块,那就要先凑到10块(获取其他更小的)-> 子问题和主问题有相同的结构,动态规划或者记忆化深度优先搜索

思路:因为是动态规划,我们需要先设定好对应的状态dp[i]的含义以及对应的状态转移方程

dp[i]:意味着要凑到金额 i 需要的最少硬币数

状态转移方程:dp[i] = min(dp[i], dp[coin] + dp[i - coin])

因此,大致的步骤如下:

①先初始化一个amount + 1长度,默认值为int.MaxValue(最大值)的dp数组

②接着遍历一次硬币数组,把遍历到的硬币面值小于amount的,设置对应dp[coin] = 1;如果发现有coin == amount 直接返回 1

③接着从1遍历到amount的数字,对于每个数字,我们都再遍历一次硬币数组,在这里面利用状态转移方程计算当前的状态值

④最后如果返回的金额值状态对应还是int.MaxValue,那就返回-1;否则返回dp[amount]

具体代码如下:

public class Solution {public int CoinChange(int[] coins, int amount) {//dp[i] 是 凑到i元所需的最小硬币数量if(amount == 0)return 0;int[] dp = new int[amount+1];Array.Fill(dp, int.MaxValue);dp[0] = 0;foreach(int coin in coins){if(coin < amount)dp[coin] = 1;else if(coin == amount)return 1;}for(int i = 1; i <= amount; i++){foreach(int coin in coins){//当前硬币小于当前要得到的总金额,同时它的另一个加数的金额也是可以凑得到的时候if(coin <= i && dp[i-coin] != int.MaxValue)dp[i] = Math.Min(dp[i], dp[coin] + dp[i - coin]);}}return dp[amount] == int.MaxValue ? -1 : dp[amount];}
}

时间复杂度:O(N * Amount)

空间复杂度:O(Amount)


优化思路:

对于状态转移方程,其实我们知道,只要coin <= amount,那dp[coin]肯定是 == 1的。

因此我们之前写的状态转移方程:

可以优化写成:dp[i] = min(dp[i], dp[i - coin] + 1)

这样我们也不用一开始还要遍历一遍硬币数组来把对应的dp[coin]设置为1了

具体代码如下:

public class Solution {public int CoinChange(int[] coins, int amount) {//dp[i] 是 凑到i元所需的最小硬币数量if(amount == 0)return 0;int[] dp = new int[amount+1];Array.Fill(dp, int.MaxValue);dp[0] = 0;for(int i = 1; i <= amount; i++){foreach(int coin in coins){//当前硬币小于当前要得到的总金额,当前这个硬币+另一个金额数if(coin <= i && dp[i-coin] != int.MaxValue)dp[i] = Math.Min(dp[i], dp[i - coin] + 1);}}return dp[amount] == int.MaxValue ? -1 : dp[amount];}
}

时间复杂度:O(N * Amount)

空间复杂度:O(Amount)


其他思路:

当然,这题也可以用深度优先搜索 + 记忆化剪枝的方式来解决

我们用一个长度为amount + 1的数组 count[]来记录每个金额需要的最少硬币数

深度优先搜索的递归函数的返回值是当前金额需要的最小凑配硬币数量

深度优先搜索的递归函数每次传入金币数组当前还需要凑配的金额rem,出口就有三个:

①当前需要凑配的金额为负数的时候,返回-1

②当前需要凑配的金额为0的时候,返回0

③当前需要凑配的金额已经记录在数组中,直接返回

而在具体的逻辑处理则是:

遍历硬币数组,用rem - coin进行递归搜索得到结果值

如果结果值在合理区间内(>= 0 ) 而且 比当前已经记录的最小硬币数还小,则更新最小硬币数

最后如果当前最小硬币数不为初始设定的最大值,则返回最小硬币数,否则返回-1

具体代码如下:

public class Solution {private int[] count;public int CoinChange(int[] coins, int amount) {count = new int[amount+1];return dfs(coins, amount);}public int dfs(int[] coins, int rem){if(rem < 0) return -1;  //说明当前凑不成if(rem == 0) return 0;  //说明已经凑成了if(count[rem] != 0) return count[rem];  //说明之前已经凑好过这一部分//配对的另一半金额需要的最少硬币数int min = int.MaxValue;foreach(int coin in coins){//根据当前硬币的面值,去寻找另一半配对的金额int res = dfs(coins, rem - coin);//如果配对金额找得到,而且配对花的硬币数是最少的,就更新为新的最少硬币if(res >= 0 && res < min){min = res + 1;}}count[rem] = min == int.MaxValue ? -1 : min;return count[rem];}
}

时间复杂度:O(N * Amount)

空间复杂度:O(Amount)


总结:

①如果是很明显当前状态的结果值可以通过拆分为更小的子状态来得到的,那就是可以用深搜+记忆化 或者 动态规划来处理的问题

②对于动态规划的问题,我们要明确好状态dp[i]以及它对应的状态转移方程

③这里的状态转移的关键的每个硬币的默认面值

http://www.dtcms.com/a/394562.html

相关文章:

  • 2015/07 JLPT听力原文 问题四
  • Redis集群实验
  • 昇腾生态双支柱:MindSpore 与 CANN 的全栈技术解析
  • YOLO系列——实时屏幕检测
  • 牛客算法基础noob49 上三角矩阵判定
  • autosar 中OS模块理解
  • 通俗范畴论17.2 向量空间的对偶与双对偶
  • huggingface_hub 安装部署问题汇总
  • 在我的Java项目中为什么使用AllArgsConstructor注解注入的方式启动报错了:
  • π0:一个 VLA 流匹配模型用于通用机器人控制(又称 pi0)
  • Information theorem-Entropy
  • 编译原理实验报告——词法分析程序
  • 整体设计 完整的逻辑链条 之4 认知逻辑视角 —— 前序驱动的认知演进体系 之2
  • C/C++正则表达式PCRE2库
  • 基于python大数据的声乐信息分类评测系统
  • 永磁同步电机无速度算法--改进型超螺旋滑模观测器
  • Linux0.12的中断处理过程源码分析
  • 进程控制(Linux)
  • 【C++】——string类的使用(详细讲解)
  • 借助 Amazon ECS 全新的内置蓝绿部署功能,加速安全的软件发布进程
  • 【脑电分析系列】第24篇:运动想象BCI系统构建:CSP+LDA/SVM与深度学习方法的对比研究
  • 【论文速递】2025年第22周(May-25-31)(Robotics/Embodied AI/LLM)
  • MySQL 5.7 多实例部署完整指南(基于二进制包)
  • Git的使用——Git命令、密钥/私钥、文件推送/提交、分支增删改查、文件回滚、.gitignore文件忽略
  • [已更新]2025华为杯D题数学建模研赛D题研究生数学建模思路代码文章成品:低空湍流监测及最优航路规划
  • [C++类的默认成员函数——lesson5.构造函数析构函数]
  • 第二十七章 ESP32S3 INFRARED_TRANSMISSION 实验
  • ✅ Python车牌识别计费系统 PyQt5界面 YOLOv5+CRNN 深度学习 MySQL可视化 车牌检测(建议收藏)
  • 盛水最多的容器_优选算法(C++)双指针
  • QT-串口,完结!