LeetCode322.零钱兑换

文章目录

  • 题目描述
  • 解题思路
    • 递归
    • 记忆化搜索
    • 动态规划
      • 另一种实现

题目描述

https://leetcode.cn/problems/coin-change/description/?envType=study-plan-v2&envId=top-interview-150
给你一个整数数组 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. 这种找路径,找方法的题一般可以使用回溯法来解决,回溯法也可以说是树形图法,解题的时候使用类似于树状图的结构,使用 自顶而下 的方法。

  2. 而在回溯法中,如果含有很多的重复的计算的时候,就可以使用记忆化的搜索,将可能出现的重复计算大状态使用一个数组来保存其值,在进行重复的计算的时候,就可以直接的调用数组中的值,较少了不必要的递归。

  3. 使用了记忆化搜索后,一般还可以进行优化,在记忆化搜索的基础上,变成 自底而上 的动态规划。

在这里插入图片描述

递归

使用递归就是关键是知道递归函数是用来干什么的,但这里使用递归会超时,因为有太多的重复计算。

class Solution {
    int res = Integer.MAX_VALUE;
    public int coinChange(int[] coins, int amount) {
        if(coins.length == 0){
            return -1;
        }

        findWay(coins,amount,0);

        // 如果没有任何一种硬币组合能组成总金额,返回 -1。
        if(res == Integer.MAX_VALUE){
            return -1;
        }
        return res;
    }

    public void findWay(int[] coins,int amount,int count){
        if(amount < 0){
            return;
        }
        if(amount == 0){
            res = Math.min(res,count);
        }

        for(int i = 0;i < coins.length;i++){
            findWay(coins,amount-coins[i],count+1);
        }
    }
}

记忆化搜索

记忆化搜索其实就是在递归的时候,把每个状态保存起来,这样我们递归过程中使用到的重复的结果的时候,不需要在去重新计算,直接从数组中取值,就可以加快速度了。
在这里插入图片描述

从图中可以看出,里面有很多的重复节点,我们使用memo[]来保存节点,memo[n]表示钱币n可以被换取的最少的硬币数,不能换取的话赋值-1。
findway函数的目的是为了找到amount数量的零钱可以兑换的最少硬币数量,返回其值int。
在进行递归的时候,mome[n]被复制了,就不用在继续递归了,可以直接的调用。

class Solution {
    int[] memo;
    public int coinChange(int[] coins, int amount) {
        if(coins.length == 0){
            return -1;
        }
        memo = new int[amount];

        return findWay(coins, amount);
    }

    // memo[n] 表示钱币n可以被换取的最少的硬币数,不能换取就为-1
    // findWay函数的目的是为了找到 amount数量的零钱可以兑换的最少硬币数量,返回其值int
    public int findWay(int[] coins, int amount){
        if(amount < 0){
            return -1;
        }

        if(amount == 0){
            return 0;
        }

        // 记忆化的处理,memo[n]用赋予了值,就不用继续下面的循环
        // 直接的返回memo[n] 的最优值
        if(memo[amount - 1] != 0){
            return memo[amount - 1];
        }

        int min = Integer.MAX_VALUE;
        for(int i=0; i < coins.length; i++){
            int res = findWay(coins, amount - coins[i]);
            if(res >= 0 && res < min){
                min = res + 1;// 加1,是为了加上得到res结果的那个步骤中,兑换的一个硬币
            }
        }
        memo[amount - 1] = (min == Integer.MAX_VALUE? -1 : min);
        return memo[amount - 1];
    }
}

动态规划

记忆化搜索是在递归的基础上,进行优化。先从memo[amount - 1]开始,从上到下。
动态规划是从memo[0]开始,从下到上。

class Solution {
    
    public int coinChange(int[] coins, int amount) {
        // 自底向上的动态规划
        if(coins.length == 0){
            return -1;
        }

        // memo[n]的值: 表示的凑成总金额为n所需的最少的硬币个数
        int[] memo = new int[amount + 1];
        memo[0] = 0;
        for(int i=1; i<= amount; i++){
            int min = Integer.MAX_VALUE;
            for(int j=0; j<coins.length; j++){
                if(i - coins[j] >= 0 && memo[i-coins[j]] < min){
                    min = memo[i - coins[j]] + 1;
                }
            }

            memo[i] = min;
        }
        return memo[amount] == Integer.MAX_VALUE ? -1 : memo[amount];
    }
}

另一种实现

memo[i]有两种实现方式,取两者的最小值

  1. 包含当前的coins[i], 那么剩余钱就是i - coins[i], 这种操作要兑换的硬币数是memo[i -coins[j]] + 1
  2. 不包含当前的coins[i],那么要兑换的硬币数就是memo[i]
class Solution {
    
    public int coinChange(int[] coins, int amount) {
        // 自底向上的动态规划
        if(coins.length == 0){
            return -1;
        }

         // memo[n]的值: 表示的凑成总金额为n所需的最少的硬币个数
        int[] memo = new int[amount + 1];
        // 给memo赋初值,最多的硬币数就是全部使用面值1的硬币进行换
        // amount + 1 是不可能达到的换取数量,于是使用其进行填充
        Arrays.fill(memo, amount + 1);
        memo[0] = 0;
        for(int i=1; i<=amount; i++){
            for(int j=0; j<coins.length;j++){
                if(i - coins[j] >= 0){
                     // memo[i]有两种实现的方式,
                    // 一种是包含当前的coins[i],那么剩余钱就是 i-coins[i],这种操作要兑换的硬币数是 memo[i-coins[j]] + 1
                    // 另一种就是不包含,要兑换的硬币数是memo[i]
                    memo[i] = Math.min(memo[i], memo[i-coins[j]] + 1);
                }
            }
        }

        return memo[amount] == (amount + 1)? -1 : memo[amount];
    }
}

题解参考:
作者:sugar
链接:https://leetcode.cn/problems/coin-change/solutions/137661/javadi-gui-ji-yi-hua-sou-suo-dong-tai-gui-hua-by-s/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

相关文章

考研规划,这么学上岸率比985的学霸还高!

我觉得985考研上岸率低是可以理解的 因为大家本科能考上985&#xff0c;那研究生大概率会报考和本学校差不多或者更高水平的院校&#xff0c;甚至清华北大都有人敢报&#xff0c;去实现自己本科没有实现的梦想。 而且985其实保研的比例很高&#xff0c;一般有30%的保研比例了…

亚马逊测评自养号技术全攻略:一站式解决方案

在跨境电商这行&#xff0c;产品测评可是个大问题。如果你的商品销量少&#xff0c;评价也不多&#xff0c;那买家就很难注意到你的产品&#xff0c;更别提下单购买了。毕竟&#xff0c;大家都喜欢跟风买那些已经有很多人好评的产品&#xff0c;而不是冒险尝试一个全新的。 我们…

基于JSP技术的社区疫情防控管理信息系统

你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;JSP 数据库&#xff1a;MySQL 技术&#xff1a;JSPJavaBeans 工具&#xff1a;MyEclipse、Tomcat、Navicat 系统展示 首页 用户注册与登录界…

《大宅门》特别活动走进李良济,开启探寻中医药文化之旅!

《大宅门》话剧将于6月14-16日在苏州湾大剧院上演&#xff0c;为了让大家了解到中医药知识&#xff0c;6月2日&#xff0c;李良济携手苏州湾大剧院举办《大宅门》特别活动“探寻中医药文化之旅”&#xff01; 6月2日下午&#xff0c;大家一起走进李良济&#xff0c;深度了解传统…

Django框架中级

Django框架中级 – 潘登同学的WEB框架 文章目录 Django框架中级 -- 潘登同学的WEB框架 中间件自定义中间件常用中间件process_view() 使用中间件进行URL过滤 Django生命周期生命周期分析 Django日志日志配置filter过滤器自定义filter 日志格式化formatter Django信号内置信号定…

51单片机STC89C52RC——1.1点亮一个LED

目录 STC单片机模块 LED模块 创建Keil项目 代码 效果 STC单片机模块 我们程序中要点亮的LED灯的位置如下图。 我们程序要用到的针脚如下图 LED模块 电路图如下 8个LED&#xff0c;全部点亮 每一bit位 都需要设置为0 二进制是0000 0000 。如果只点亮D1一个&#xff…

进口电动低温调节阀的作用-美国NOTON

进口电动低温调节阀在低温环境下的精确控制、广泛的工业应用、高效能设计、耐低温性和密封性、稳定性及可靠性以及安全性等方面发挥着重要作用。 进口电动低温调节阀的作用主要体现在以下几个方面&#xff1a; 低温环境下的精确控制&#xff1a; 进口电动低温调节阀是一种专为…

jenkins插件之Jdepend

JDepend插件是一个为构建生成JDepend报告的插件。 安装插件 JDepend Dashboard -->> 系统管理 -->> 插件管理 -->> Available plugins 搜索 Jdepend, 点击安装构建步骤新增执行shell #执行pdepend if docker exec phpfpm82 /tmp/composer/vendor/bin/pdepe…

怎么把wmv格式转换成mp4?四种将wmv转成MP4格式的方法

怎么把wmv格式转换成mp4&#xff1f;在微软操作系统中&#xff0c;我们经常会遇到wmv格式的视频文件。这种由微软开发的视频格式在微软平台上有很好的兼容性&#xff0c;但它也存在一些被忽视的缺点。首先&#xff0c;wmv格式支持数字版权管理&#xff0c;这意味着某些视频可能…

期权有用吗?期权都有哪些用途?

今天带你了解期权有用吗&#xff1f;期权都有哪些用途&#xff1f;期权和期货作为衍生工具,都有风险管理、资产配置和价格发现等功能。 期权有用吗&#xff1f; 期权作为一种衍生金融工具&#xff0c;具有多种用途和好处&#xff0c;对不同类型的投资者和市场参与者来说&#…

Ubuntu编译指定版本NVMe Cli工具

1.克隆nvme-cli的存储库&#xff08;repository&#xff09;&#xff1a; git clone https://github.com/linux-nvme/nvme-cli.git2. 进入nvme-cli目录&#xff0c;并切换到指定版本&#xff1a; cd nvme-cli git checkout v1.93. 编译nvme-cli&#xff1a; make4. 安装nvme…

剪画小程序:图片去除文字,我用它只要10秒!

Hello&#xff0c;大家好呀&#xff01;我是不会画画的小画~ 图片上的文字该如何去除&#xff1f; 在工作或者学习中&#xff0c;我们常常需要处理一些图片文件&#xff0c;比如扫描的文件、 电子文档等。有时候&#xff0c;图片上可能会有文字&#xff0c;这时候需要将图片…

鸿蒙开发:从入门到实战!

一&#xff0c;默认模版中是容器Row或者Column中添加一个Text文本&#xff0c;我们可以尝试一下修改它的内容和样式&#xff0c;对UI语法有一个初体验&#xff1a; // 文本内容 Text("沉默的闪客") // 字体大小 .fontSize(50) //背…

VS-qt中运行程序时报错:fatal error RC1015:cannot open include file ‘afxres.h‘

开发环境&#xff1a;VS2015 qt5.12.10 点击运行时报错如下&#xff1a; 搜索了下afxres.h文件&#xff0c;发现位置如下&#xff1a; 看样子是VS中少安装了部分模块导致的&#xff0c;&#xff0c;看了同事的电脑&#xff0c;该文件应该是在以下目录中的&#xff1a; 所…

从零开始:如何在直播应用中集成美颜SDK和美颜插件

本篇文章&#xff0c;小编将详细介绍如何从零开始&#xff0c;在直播应用中集成美颜SDK和美颜插件。 一、准备工作 确定需求 在开始集成美颜SDK之前&#xff0c;首先需要明确需求。考虑以下几个问题&#xff1a; 直播应用的目标用户是谁&#xff1f; 需要集成哪些美颜功能&…

gbase 扩容 集群数据同步 主备切换

问题&#xff1a; 问题1磁盘满 1.原本是100G的大小&#xff0c;我们实际还没接入真正业务&#xff0c;昨日空间满了&#xff0c;需要帮忙看下是什么原因导致磁盘满的吗 数据库是每天备份一次&#xff0c;是不是备份的太频繁&#xff0c;还是数据量的问题导致&#xff0c;需要…

Apache Doris 基础 -- 数据表设计(模式更改)

用户可以通过schema Change操作修改现有表的模式。表的模式主要包括对列的修改和对索引的修改。这里我们主要介绍与列相关的Scheme更改。对于与索引相关的更改&#xff0c;可以查看数据表设计/表索引&#xff0c;查看每个索引的更改方法。 1、术语 基本表&#xff08;Base Ta…

Python 快速查找并替换Excel中的数据

Excel中的查找替换是一个非常实用的功能&#xff0c;能够帮助用户快速完成大量数据的整理和处理工作&#xff0c;避免手动逐一修改数据的麻烦&#xff0c;提高工作效率。要使用Python实现这一功能&#xff0c; 我们可以借助Spire.XLS for Python 库&#xff0c;具体操作如下&am…

SuperPanel不只是母排设计软件,还是母排管理软件!

盘厂的铜排成本约有20%&#xff0c;以1亿产值客户为例&#xff0c;约有2000万的铜排成本。 铜价不断高涨&#xff0c;有效的管理铜排&#xff0c;可以达到节约母排&#xff0c;精准报价&#xff0c;精准确定采购时间&#xff0c;减少资金占用等效果。 盘厂铜排管理现状 01 只…

图的相关种类

目录 数据类型 存储结构 邻接矩阵表示法 无向图 邻接矩阵表示 有向图 网 实现 邻接矩阵表示 存储结构 创建无向图 优点 缺点 邻接表法表示 表示无向图 表示有向图 存储结构 无向网 特点 十字链表与多重表 十字链表 存储结构 多重表 存储结构 数据类型 存…