ok,下面我们再看一个例子。 这个例子呢比较有意思。 这个例子名字叫放苹果。这是open jar 的上面比较经典的一道题目。 我们来看一下这个题目。说啊,有M个同样的苹果。 这M个苹果呢一模一样没有区别。现在呢要把这M个苹果 放在N个同样的盘子里头。 也就是说有N个一模一样的盘子,现在呢我们 要把这M个苹果放到这N个盘子里头。 而且呢你喜欢怎么放都行。允许有的盘子空着不放。 它允许可以你有空的盘子不放。他问你啊 请问一共有多少种不同的 分法或者放法? 也就是说要把这M个一模一样的苹果放到N个一模一样的盘子上 并且呢允许有的盘子空着不放。 请问有多少种放置方法? 在这呢它特别给了一个提示,也就是说这个放置方法 跟顺序是没关系的,也就比方说如果你有7个苹果3个盘子 你第一个放5个,第二放1个,第三个放1个。 这种放法其实跟第一个放1个,第二放5个,第三个放1个是 同一种分法,也就是说跟顺序排列顺序没有关系。 也就是说这个题目提给我们的问题就是 当我们有M个一模一样的苹果要放入N个一模一样的盘子里头的时候 有多少种放法? 这儿有一个输入输出的例子,比方说有7个苹果 3个盘子的时候那么它放法的总数就是8。 也就是说程序的输出应该是8。那对于这样一个问题我们应该怎么去求解呢? ok 我们啊仍然采用刚才使用过的那个办法。 现在我们假设 存在这样一个函数f(m,n),它能告诉我们答案。 也就是说我假设f(m,n)能告诉我们当m个苹果 放到n个盘子里的时候有多少种的解决方案。 那么接下来呢我们就来分析一下f(m,n)的执行过程。 也就是说我们假设存在这样一个函数它能告诉我结果。 那么在有这样一个假设的前提下呢我们去分析一下 这个函数是如何来进行计算的。 那怎么进行分析呢? 那么对于这样一个问题我们就可以分情况来讨论。 比方说我们可以这么来做。 首先我们来分析一下当盘子的数目 多于苹果数目的时候可能出现的情况。 比方说我们现在面临的状况是这样的。 我们一共有1234567,7个苹果。 但是摆在我们面前呢有9个一样的盘子。 现在呢盘子的数目比苹果的数目要多。 那么现在我们就要考虑一下了,既然 盘子的数目比苹果的数目还要多,那就意味着 就算每个盘子里头只放一个苹果。 比方说这儿有9个盘子,就算每个盘子里头只放 一个苹果也总会有两个盘子是 空着的。 也就是说这两个空着的盘子其实跟放苹果办法那个放法的数目 是完全没有关系的。 也就是说在这种情况下当盘子的数目比苹果的数目 还要多的时候我们完全可以把多余的盘子给 砍掉。让它消失掉。 那么进行这样一个转换砍掉多余的盘子呢完全不会影响我们最终的计算结果。 于是呢我们就得到了第一个规律。 也就是说如果n大于m这个条件成立的话 那么其实在这种情况下f(m,n)其实就等于 f(m,m)是不是这个意思啊?因为多余的盘子是完全用不着的。 这是我们得到的第一个结论。 那么接下来呢我们再去分析另外 一种情况。也就是说当苹果的数目 大于或者等于盘子的数目的时候会是什么样的状况? 比方法说现在我们有1,2,3,4,5,6,7,8,9,10,11,12,12只苹果。 但是呢我们有9个盘子放在这儿。那么到底有多少种的放法呢? 那么在这儿我们就把所有的放置方法 分成两类。那么根据这个题的提议 在把苹果放到盘子上面的时候 允许有的盘子空着不放。 那么根据这个条件我们就把所有可能的放置方法 分成两大类。一类呢是有盘子空着的情况。 另一类呢是没有盘子空着的情况。分成这两大类。 那么在这种情况下 那么所有可能存在的那些放法的那个数目就等于 分别在这两种情况下出现的放法数目的 和。那么说到这儿我们就可以感受到我们的解决思路了。 也就是说呢如果盘子的数目比苹果的 数目多,那么我们就可以砍掉多余的盘子 使得苹果的数目保持大于或等于盘子。 然而呢当苹果的数目大于或等于盘子的时候 那么所有可能存在的放置方法的数目就等价于 这两种情况下所出现的放置方法的数目的 和。所以无论如何 我们都可以把所有可能存在的放置方法 分成这两大类。一个是有盘子 空着的情况,一个是没盘子空着的情况。 所以啊只要我们分析清楚这两种情况下放置方法的数目应该如何计算 我们就能够得到最后的结果了。那么现在呢我们就 先来对第一种情况就是有盘子空着的这种情况 进行分析。那么对这一类情况也就是说 如果这种放的方法总是至少有一个盘子空着,那么就意味着 这个空的盘子对于放置方法的 数目是没有任何影响的。 因为你假设在这种情况下总会至少有一个盘子空着。 就像我们看到的这种情况,有12个苹果在这儿,但是呢我们总是有一个盘子让它保持 空着不放,那么在这种情况下这个盘子是否存在 其实对于放置方法的数目是没有任何影响的。 因为你已经假设它总是空着。所以说在这种 情况下当我们仍掉这个总是空着的盘子 对于放置方法的数目是没有任何影响的。 也就是说我们可以得到这样一个数字。 也就是f(m,n)如果m大于n 并且呢总是至少有一个盘子空着,那么 f(m,n)就等于f(m,n-1),因为n呢代表盘子的数目。 而在这种情况下呢又至少有一个盘子是空着的,所以说 我们把这一个盘子扔掉,也就是n-1,对于放置方法的数目是没有 任何影响的。所以说我们可以得到这样一个等式。这是第一种情况。 当有盘子空着的时候。现在呢我们 再来讨论另外一种情况,当没有盘子空着的时候。 比方说我们现在的这种状况下,在现在的这种状况下 每个盘子里面都至少放有一个苹果。 也就是说所有的盘子都没空着。那么在这种情况下 你想一下,放置方法的数目 跟什么东西没有关系啊?有一个东西又可以减掉了。哪个东西啊? 每只盘子里至少放着的那只苹果。因为在这种情况下所有的盘子里头 都至少要放一只苹果。所以说 至少放置的那一只苹果如果把它剪掉的话 那么对于放置方法的数目,也没有 任何影响。于是呢我们就又得到另外一个等式。 如果没有盘子空着,那么 f(m,n) 实际上就等于 f,m-n,然后n。 那么说到这儿有的同学可能又发现了,哎,当每个盘子里都减掉这个 苹果以后啊,我们又碰到了刚才我们讨论过的那种情况。也就是说 盘子的数目其实远远大于苹果的数目。 对不对?那这个时候呢我们又可以减掉 所有多余的盘子。啊,那么在减掉所有多余盘子的基础上呢, 我们又得到了一种新的情况就是盘子数目跟苹果数目是相等的。 那么在这种情况下呢所有的放置方法又可以被分成 两类:一类是有盘子空着,一类是没盘子空着。 啊,那这个时候呢,我们又可以按照刚才的那种方法,再进行分析。 所以说啊,按照这个思路,我们可以一直分析下去。 比方说对于这种情况,那么如果有一个盘子空着其实它就等价于把这个盘子减掉。 然后如果所有的盘子都放着苹果呢,又可以等价于把每个苹果都减掉的这种情况。 那接下来呢,又会出现盘子的数目多于苹果的情况,所以又把多余的盘子再减掉。最后只剩下 一个盘子或者是一个苹果。 这个时候呢,就不用再分析了,对不对?啊,那按照这样的 一个规律其实我们就把所有可能出现的情况全部都分类, 分析了一遍。而我们要获得的那个结果呢,无非是把所有这些情况下的结果 加起来,就可以了。对不对? 就是这样的一种分析方法。 那么把刚才这个分析的思路啊,给它写下来,我们就 获得了这样一个函数。这个函数呢,非常非常的简明。 别看这个题很复杂,啊,但是写出来的函数都非常的简明。函数的名字呢,叫做count。 它表示,当把m个苹果放到n个盘子上的时候,一共 有多少种的放法。那么,跟我们刚才讨论的一样, 那么这个程序呢,分情况来探讨了不同情况下的处理。 如果盘子的数目大于苹果的数目,那么我就减掉多余的盘子。也就是说如果 m小于n,那我就return count(m,m)。如果苹果的数目大于或者等于盘子的数目, 那么我就区分清楚,如果有盘子空着,那么 count (m,n) 其实就等于 count (m,n-1)。如果没有盘子空着,那就相当于每个盘子上都减掉一个苹果 也就是说count(m,n)就相当于count (m-n,n)。同时呢,在这指明了边界条件, 也就是说如果m或者是n小于等于0的话,那我们就直接return 1。 那在这种情况下只有一个解决方案。那么在这个函数的基础上呢,把程序补充完整,就是这样的。 那么这个程序的运行结果呢,就是这样的。那在这儿呢,我做了这么一个测试, 把100个苹果放到100 个盘子上一共有多少种的放法呢? 经过统计,一共有这么些种的放法,那这个数字非常大。 啊,那需要说明的是呢,这个程序啊,在我的笔记本上,至少跑了有十几秒钟。 十几秒钟之后,才返回来结果。那大家呢,也可以把这个程序抄写下来,在自己的电脑上,去运行一下这个程序。 那么通过运行这些递归的程序啊,你就会发现其实递归的 程序它的运算量还是很大的。虽然程序非常的简短,但它 的运算量有可能是非常大的。Ok,这就是放苹果这道题目。 在这儿呢,我也想说明一下,其实呢,放苹果这道题目的难度,也是不小的。如果我们 也做一个星级评定的话,那么五星呢,我也可以给到四颗星了。所以说如果大家一时还不能明白, 不要着急,慢慢地琢磨一下,就可以了。Ok,那么通过以上这两个例子啊, 我们可以看到,其实递归函数啊,在某些场景中能够啊, 帮助我们来自动地分析一个问题。 就比方说我们遇到的逆波兰表达式和放苹果,其实我们的程序都非常非常的 简短。那,这么简短的程序怎么能够分析清楚这么多的情况呢? 所以说啊,在这种场景中啊,递归其实在帮我们做 自动的分析。也就是说我们的递归函数是具有一定的 分析能力的。那当我们面临类似的问题的时候,我们如何去做才能 找到这个帮助我们自动进行分析的递归函数呢?我们可以啊,这样去做。 首先呢,我们可以先假设存在一个这样的函数。也就是说, 我先假设有这么一个函数,它呀能够帮我们进行分析并且给出答案。 就比方说在刚才的例子里头,我们所定义的notation,和分苹果的程序里头我们定义 的count,我们都先假设存在这么一个函数,它能够给出我们一个 分析的结果。然后呢,在这个假设的前提 下,我们再去分析,如何去解决这个问题。 也就是说,我们假设存在这么一个函数了,然后我们再去分析在这个函数的辅助 之下,这个问题是如何一层一层解决的。比方说我们在逆波兰表达式里头,我们知道 任何一个notation函数它都具备这样一些功能。那么在分苹果的例子里呢,我们知道 原来对于每一个我们定义的这个递归函数啊,我们都可以去分情况的去讨论。每一种情况下,它是如何 变化的。所以通过这个分析呢,我们就 利用了notation 去表示 notation。 利用了count去表示count。从而呢, 我们也就搞清楚了这个递归函数到底是如何完成计算的。 那么在这个的基础上呢,我们还必须要搞清楚,最简单的情况下函数返回的结果会是什么。 比方说在逆波兰表达式的例子里头,那么最简单的情况就是我读到 的不是一个操作符,而是一个普通的字符。这个时候我就直接返回一个数, 就可以了。那么在分苹果的这个例子里头呢,最简单的情况无非也就是m或者n小于等于1的时候。那么这个时候呢, 只有一个解决方案。那么对于这一类的问题,当我们搞清楚了这三个问题以后, 那么就可以基于我们的分析,写出递归函数来了。Ok,这是关于这个场景下 递归函数的讨论。 好,那么在分析了这三个场景之后啊,我们 稍微做一个总结。 那么在这节课里头呢,我们在三个比较常见的场景之下,讨论了 递归函数的作用。这三个场景呢,分别是用递归来实现递推, 用递归呢,来模拟连续发生的动作。第三个呢,就是用递归 来进行所谓自动的分析。那Ok我们在这儿呢,稍微总结一下, 这三个场景之下,我们给出来的一些解决方案。 首先,在用递归来解决具有递推性质的问题的场景中, 我们是按照这种方法来寻找递归函数的。那么在 这种场景中呢,首先我们看问题的视角就要发生一个变化。 我们应该把我们的关注点啊,放到最终求解的那个目标上。比方说 切饼问题我就直接去考虑,第n刀切下去的时候,我会获得一个什么样的结果。 那么在这个基础上呢,我要寻找这个递归函数的第n次执行和第n-1次执行 之间的关系。并且呢要搞清楚第1次执行,也就是边界情况下, 递归函数的返回结果。那么有了这三个条件, 你就可以去书写那个递归函数了,这是这个场景。 那么在,用递归来模拟连续发生动作的这么一个场景中呢,为了找到递归 函数啊,我们应该这么来做。首先我们要搞清楚那个连续发生的动作到底是指的什么呀? 因为通常啊,只有我们确定了哪些动作是我们要表达的 连续的动作,我们才能够给出递归函数来。比方说,在汉诺塔的问题上 如果你不能够搞清楚你需要连续执行的动作 其实就是把一些盘子经过一个柱子搬到另外一个柱子, 那么你就没办法给出那个move函数来。 啊,那个参数你都不知道该怎么去写,那么通常呢,在这一类的问题中, 这第一步啊,也是一个难点。其实在第一步的时候,你可能就需要确定 函数的参数有哪些。 那么在我们搞清楚连续发生的动作到底是什么的这个基础上,我们再去搞清楚不同次 动作之间的这种关系。你比方说,在进制转换的例子里头其实上一次动作啊, 求出来的那个商,就是下一次动作的输入。我们要搞清楚这个关系。 然后在这个基础上呢,再搞清楚那个边界条件是什么。那么有了这三个条件,你也就可以书写 用于这种场景的递归函数了。那么第三种情形,利用递归来进行自动的分析。 那么这个呢,是我们刚刚讲过的方法。那么在这种场景之下呢,我们往往会先 假设有一个函数能够给出这样一个答案。 然后呢,在这个前提下我们再去分析这个问题是如何被解决的。最后呢 我们再搞清楚最简单的情况下,也就是边界的情况,到底是什么。那么有了这三点, 你也就可以在这个场景之下,去利用递归了。我在这儿啊,还是想要 强调一点。那么其实啊,这三个场景之间啊, 并没有明确的界限。在很多情况下,由于看问题视角的不同,你 会觉得一个问题,应该属于这个场景。另一个同学觉得这个问题属于那一个场景。 Anyway,都不要紧。其实呀,这三个场景向我们给出来的这些方法,基本上都是 相通的。所以说呢,我就希望大家在学习使用递归的这个过程里头, 如果遇到问题,你就可以啊,回想一下这些典型的场景。想一下 在这样一些典型的场景之下,我们是如何去求解问题的。那么通过这样一种模仿的方法, 将会非常有助于你在这部分的这一个学习。那么今天的课程呢,我们就讨论到 这里。最后呢,我还是希望大家要好好地琢磨一下这些问题。如果碰到不明白的问题呢,即 时通过论坛,反馈给我们。最后谢谢大家。

java递归分苹果_递归应用示例(放苹果)[较难 选听]相关推荐

  1. 苹果白屏一直显示苹果_最新消息显示:苹果还要发新品

    距离2020年结束已经进入了倒计时阶段,但最新消息显示苹果可能还会在这个最后的时间节点上召开一场新品发布会. 今日,有外媒援引一份苹果内部备忘录报道,称苹果通过内部备忘录向服务提供商发送通知,计划在美 ...

  2. java递归分苹果_递归较难题——分苹果问题

    第四届程序设计大赛 苹果 Time Limit:1000MS  Memory Limit:65536K Total Submit:90 Accepted:48 Description 把M个同样的苹果 ...

  3. 递归与分治java策略实验报告_递归与分治策略–计算机算法设计与分析

    递归概念:直接或者间接调用自身的算法,称为递归运算. 分治思想:把一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相等,递归解决子问题后再将结果合并 下方为一些应用函数.因为 ...

  4. java递归获取文件名_递归打印文件名

    class="java" name="code">import java.io.File; import java.io.IOException; pub ...

  5. java 应用分模块_在Java 11中创建一个简单的模块化应用教程

    模块化编程使人们能够将代码组织成独立的,有凝聚力的模块,这些模块可以组合在一起以实现所需的功能. 本文摘自Nick Samoylov和Mohamed Sanaulla撰写的一本名为Java 11 Co ...

  6. python函数可以递归调用吗_递归调用函数

    我有10张,20张,50张钞票,当我需要支付任何金额时,我需要找到最好的组合.例如,当我需要付7英镑时,我会付5英镑和2英镑的钞票 我有一个函数可以计算这个.但我需要运行同一个函数3到4次,如下所示. ...

  7. java猴子分桃_算法——猴子分桃

    想做些有关"算法"的练习题,在网上无意间看到了一道很经典的算法题--猴子分桃,于是百度了一下,才发现这道题的相关文档很多很多,但最多的也就是使用C++或者Java来解决这道题,而自 ...

  8. 斐波那契递归调用次数_递归求解斐波那契数列的时间复杂度——几种简洁证明...

    TL:DR: 暴力递归求解斐波那契数列的时间复杂度的紧界不是 ,而是 . 本文将给出几个简洁证明 用最暴力的方法求解斐波那契数列,时间复杂度是多少?具体地说,就是求下面这个程序的复杂度: def fi ...

  9. 汉诺塔递归的空间复杂度_递归思维——快速排序的详细设计过程

    理解递归的运行模型(https://zhuanlan.zhihu.com/p/166173378)之后,就能根据递归函数的静态代码推算执行结果了. 递归思维,是理解递归的基础上,用递归研究并解决问题的 ...

最新文章

  1. PostgreSQL 创建库时如何指定 Collate, Ctype
  2. Linux服务笔记之二:SSH远程登录
  3. 如何编写无法维护的代码_编写可维护的前端代码
  4. 网络编程应用:基于TCP协议【实现对象传输】--练习
  5. C语言再学习 -- 再论数组和指针
  6. python,面向对象的各种方法
  7. Linux下恢复误删文件:思路+实践
  8. jquery 获取 id ,但是id 里面不能有. 这个符号
  9. new HashMap<String, Object>();
  10. 信号与信号分解理解总结
  11. 【干货】如何搭建靠谱的数据仓库.pdf(附下载链接)
  12. 跟着鬼哥学爬虫-2-糗事百科
  13. 服务器PCI插槽上的固态硬盘,固态硬盘常见接口图解
  14. 工作占用了太多私人时间_当公司老板过多占用你的个人时间,虽然不是什么大事但很想辞职怎么办?...
  15. Eslint:Parsing error: The keyword ‘interface‘ is reserved
  16. 这4个资源搜索网站,你可能还不知道,但非常的实用
  17. 2022“高考记忆” 已打包完成,请查收!
  18. 黑马程序员------Java的多态性
  19. 列联表中的相关测量(卡方值与相关系数之间的转换)
  20. 易语言链接mdb和accdb数据库的两种方法

热门文章

  1. CSS几种常见的页面布局方式介绍
  2. 全局zomm缩放后echarts鼠标偏移的问题(鼠标触发提示框位置有偏差)
  3. git时光穿梭机总结
  4. 读《深度思考 让所有事情都能正确入手》
  5. miui 10 android 9.0,小米基于安卓9.0的MIUI10稳定版来了,你的手机可以更新吗?
  6. html table vtop,打造个性化的Select(可编辑)_表单特效
  7. Unity3d shader内置矩阵
  8. 习题6-8 单词首字母大写 (15 分)
  9. Android 手机浏览器的开发
  10. 什么pdf转换成excel转换器好