题目描述

给定数组arr,数组中所有的值都为正数,且不为空不重复。数组中每个数代表一种货币的面值,每种面值的货币可以使用任意张,然后,给一个aim,代表要换钱的面值,请问,用数组中的面值换钱,总共有多少种方式?

暴力递归思路

递归的第一步,将问题划分为更小的子问题,比如,数组arr[1,5,10]这三种面值的货币,aim=1000。首先,可以先取出第一种面值。假如,第一种1元的有0张,那么问题就划分为arr=[5,10],aim=1000;如果第一种1元的有1张,问题就划分为arr=[5,10],aim=999。依此类推,直到第一种货币的面值一元有1000张时,也就是超过aim,那么,第一种的所有结果都例举出来了。
因此,从上面分析中抽象出递归函数。首先,递归函数需要记录arr,和目前是第几种货币面值,也就是数组的索引,其次,还需要记录aim,当aim为0时,就找到一种换钱方法。
递归的出口是,数组遍历完最后一个,此时aim恰好为0,说明找到一个换钱方法,不为零,就不是,当然,不对的情况包含aim大于和小于的情况。
递归方法,就是设定一个res记录当前符合的换钱方式,遇到出口就返回1或0,否则,就继续向下递归。
递归代码

    public static int process(int[] arr,int index,int aim){int res=0;if(index==arr.length){res = aim==0 ? 1:0;}else {for (int i = 0; i*arr[index]<=aim; i++) {res+=process(arr,index+1,aim-i*arr[index]);}}return res;}

记忆搜索法

暴力递归时间复杂度高的根本原因,就是存在大量的重复操作,而重复操作之所以大量发生,是因为在递归的过程中,很多重复计算的结果没有记录下来,才会导致重复计算。
因此,记忆搜索法其实也很简单,就是把每一步递归的结果放入一个map中,然后每次递归前,先检查map中有没有,如果已经有结果,直接取出来,就不需要重复计算了。

动态规划法

第一步,判断是否可行?本题中间递归结果是不依赖前面的路径的,因此可行。
第二步,画图,找出递归过程的变化量,index和aim,画图。
第三步,标记结果位置,此题的结果位置为index0,aim1000。
第四步,填入已知数据,已知数据为indexarr.length这一行,aim0的位置填返回值1,其他都是0。
第五步,根据已知结果,结合递归函数,我们已知了最后一行indexarr.length的结果,就可以根据递归函数,推出indexarr.length-1这一行的结果,然后依次填完表格,直到找到index0,aim1000位置的结果,就是返回的最终结果。

动态规划和记忆搜索对比

其实,动态规划可以理解为就是记忆搜索法 。
记忆搜索法不关心到达某一个递归过程的路径,只是单纯的记录递归过程的每个结果,避免重复计算。
动态规划是通过表格来表示每个递归过程之间的顺序,每个过程依赖前面已知的结果,其实也是在记录前面的递归结果,避免重复计算,只不过是也同时保留了递归顺序之间的过程。
两者都是空间换时间的优化思想,区别在于,动态规划记录计算顺序,而记忆搜索法只是简单避免重复计算,不记录计算顺序。

因此总结一下,什么动态规划?
其本质就是利用申请的额外空间来记录每一个暴力递归的结果,下次要用的时候可以直接使用,并且记录每种递归状态之间的计算顺序,依次计算。

动态规划练习三:换钱问题(动态规划概念理解与记忆搜索法概念理解对比)相关推荐

  1. 最长公共子序列算法 java_转【算法之动态规划(三)】动态规划算法之:最长公共子序列 最长公共子串(LCS)字符串相似度算法...

    1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 2.最长公共子串 其实这是一个序贯决策问题 ...

  2. java 最少货币单元组合换钱_动态规划. 换钱的最少货币数和最多方法数

    通过对换钱类题目的学习,我们将了解到 暴力递归及优化方法 记忆搜索(优化一) 动态规划的基本实现方法(优化二) 动态规划的空间优化(优化三) 1. 换钱的最少货币数,货币可重复使用 给定数组arr,a ...

  3. 动手学强化学习(三):动态规划算法 (Dynamic Programming)

    动手学强化学习(三):动态规划算法 (Dynamic Programming) 1. 简介 2. 悬崖漫步环境 3. 策略迭代算法 3.1 策略评估 3.2 策略提升 3.3 策略迭代算法 4.价值迭 ...

  4. 动态规划C++实现--换钱的方法数(二)(动态规划及其改进方法)

    题目:换钱的方法数 给定数组 arr, arr中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求换钱有多少种方法. 将原文的伪代 ...

  5. Leetcode_打家劫舍三道题(动态规划总结)

    Leetcode_打家劫舍三道题(动态规划总结) 分类专栏: Leetcode # 动态规划 文章标签: 动态规划 leetcode 算法 LeetCode198 打家劫舍 leetCode213 打 ...

  6. 【算法之动态规划(一)】动态规划(DP)详解

    一.基本概念 动态规划(dynamic programming)是 运筹学 的一个分支,是求解决策过程(decision process)最优化的数学方法.20世纪50年代初 美国 数学家R.E.Be ...

  7. 理解系统底层的概念是多么重要

    理解系统底层的概念是多么重要                                --趋势科技邹飞评<程序员的自我修养>   关于<程序员的自我修养>这本书,最初是在 ...

  8. 深入理解正则表达式环视的概念与用法

    在<深入理解正则表达式高级教程-环视>中已经对环视做了简单的介绍,但是,可能还有一些读者比较迷惑,今天特意以专题的形式,深入探讨一下正则表达式的环视的概念与用法. 深入理解正则表达式环视的 ...

  9. 通过实例理解 RabbitMQ 的基本概念

    先说下自己开发的实例. 最近在使用 Spring Cloud Config 做分布式配置中心(基于 SVN/Git),当所有服务启动后,SVN/Git 中的配置文件更改后,客户端服务读取的还是旧的配置 ...

最新文章

  1. 使用NuGet发布自己的类库包(Library Package)
  2. linux脚本批量复制文件,shell实现scp批量下发文件
  3. css 解析 开源库_干货 | python库大全,全面高效
  4. numpy 转置_Python中Numpy.transpose()
  5. 埃森哲《技术展望2021》(中文版)
  6. Spring Cloud入门五 hystrix
  7. 计算机课题立项申报书范文,专项课题立项申报书模板.doc
  8. 微信群活跃度测试软件,微信群怎么监控活跃度?
  9. PMP 考点 第五章 项目范围管理
  10. 【论文阅读】Generalization in Reinforcement Learning
  11. 客房管理系统前台代码html,客房管理系统|客房软件|PMS系统|酒店管理系统|酒店管理软件...
  12. mybatis plus分页插件 total数为0
  13. 用计算机程序计算鸡兔同笼,Linux脚本基础篇-鸡兔同笼问题(示例代码)
  14. P2000 拯救世界(生成函数裸题+NTT高精)
  15. AI视觉千亿规模市场虚席以待 初创企业看好“算法决定芯片”路径
  16. 网易有道精品课好在哪里?有知道的大家说一说
  17. Live555本地保存H264/PCM视频音频帧附加SPS/PPS
  18. 楼宇控制系统发展过程
  19. 指针与指针变量的区别(C语言)
  20. 图形类的实现(java)

热门文章

  1. 你是怎样毁掉自己的?
  2. 一加6android p上手,一加6秒速跟进安卓P 教你尝鲜速成开发者
  3. 微信朋友验证消息是什么来源_微信好友来源怎么改?来源朋友验证消息是什么意思?...
  4. AI 医学影像公司及其产品(更新中)
  5. RT-Thread柿饼控件(3)-- Canvas
  6. PSAM 卡的应用 操作方法
  7. uniapp的项目,scss和js实现跑马灯
  8. MACS磁珠标记细胞分选技术
  9. 怎么在小程序中使用彩色图标iconfont
  10. 三种等待方式:强制等待、显式等待、隐式等待