首页 > 其他分享 >对于递归有没有什么好的理解方法?

对于递归有没有什么好的理解方法?

时间:2022-12-21 21:57:36浏览次数:71  
标签:放在 有没有 递归 圆盘 50 问题 理解 汉诺塔

 

 

作者:JoBoBo
链接:https://www.zhihu.com/question/443721615/answer/1726913861
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

学算法的时候,递归确实是最绕的,这个东西怎么说呢,思路比较反自然思维....

为啥说它反思维呢:自己调自己,而因为你在调用自己的时候只用了一个Fn-1,但事实上这个Fn-1代表了超级多个Fn-2Fn-3......,这是最让人思维感到难受的地方,但是用久了发现:真香

你只需要明白一个思想,就是面对一个看起来超级复杂难以下手的问题,目标是把它转化为一个简单的靠直觉就可以解决的问题

递归算法可以抽象为一个模版———

递归公式+递归边界=递归算法,然后我通过一个小例子来解释一下

比如排序问题,让你从大到小排100个数,你是不是会感到很头大,但是让你排两个数呢?是不是看哪个最大就行了,把它放在左边,就排好了

而递归就是把大问题抽象为极其简单的小问题,然后找到小问题和小问题之间如何组合还原为“大问题”

 

第1步,就像刚才的100个数,我是不是可以减小一下工作量,就是大的50个在左边,小的50个在右边,这样把左边和右边合在一起不就是咱们想要的排序吗

 

第2步,想要解决这个子问题,发现50个数排好还是挺头大的,那咱再减小一下工作量,对于大的50个:咱把这里面25个最大的放在左边,小的25个放在右面

........几个1、2步骤以后......

第n步,有2个数,对于这两个数,咱们终于发现,不头大了!!!把大数放在左面,把小数放在右面,这不就OK了?

 

聪明的你一定会发现,每一步咱们都在做相同的事情———把大的放在左面,把小的放在右面,然后合并左右(当然实际合并是用一个双指针实现的)

 

好了这就是一个简单例子(具体实现就是“归并排序”,能在O(N•LogN)内解决排序问题),现在咱们来总结一下这个例子

 

递归边界

当一组里只有两个数的时候,也就是我们可以秒杀得出答案的时候

 

递归公式(步骤)

1.把现在要解决的数列分成两组数量小数列大的在左,小的在右(因为目标是从大到小)

 

 

这个递归思想呢,其实就是层层剥开再细化执行,就跟总领导把大任务细化成各种方面的小任务,分配给不同部门的领导,不同部门的领导再分配给小职员 一个道理

 

就是将规模为n的问题转化规模为n-1的小问题

 

回到你提的问题汉诺塔问题,要解决N层汉诺塔问题,你要怎么做?

首先什么最简单?只有3层的时候想必大家都会做,而其实通过3层和4层的详细解法我们会发现一个规律:想要把n个圆盘转移,我们先得把上面N-1个圆盘都给清理干净才能动最底下的盘子,所以Here the thing is(规律)

1.首先,将n-1个圆盘从“起始柱”柱移到“中转”柱(解出n-1层)
2.后,将最大的圆盘从“起始柱”柱移到“目标柱
3.后,将n-1个圆盘从“中转”柱移到“目标”柱(解出n-1层)

 

那么道理懂了,那么N层汉诺塔问题的具体步骤是啥(哪个盘子从哪个柱子转移到哪根柱子)

不用想了(狗头),肯定麻烦的要死啊,但我们可以简化一下,A柱到B柱B柱到C柱......等等一系列操作通通叫做“N-1层汉诺塔问题解决步骤”,然后遇到“N-1”层的时候可以把剩下的步骤叫做“N-2”层.......等等

 

对于每一层我们都很简单,都是三步走,最后整个事情也就解决了

 

具体实现就不说了,思想get到就可以了,理解就是分分钟的事情,加油!

 

兄弟们别光收藏不点赞啊(狗头)

 

递归模块

 

 

 

对于递归有没有什么好的理解方法?

 

 

用数学代入法来理解就好。

假设我们用递归来算阶乘 f(n)

f = n =>
    n === 1 ? 1
            : n * f(n-1) 

 

f 里面用到了 f,怎么理解呢?

很简单,把式子展开即可:

看到递归了吗? 

 

先递进,再回归——这就是「递归」。

以上是 SICP 原文(有删改)。

 

标签:放在,有没有,递归,圆盘,50,问题,理解,汉诺塔
From: https://www.cnblogs.com/shoshana-kong/p/16997303.html

相关文章

  • 一文看懂什么递归(算法小结)
    前言递归是算法中一种非常重要的思想,应用也很广,小到阶乘,再在工作中用到的比如统计文件夹大小,大到Google的PageRank算法都能看到,也是面试官很喜欢的考点最近看了不少......
  • 算法-如何理解递归,写好递归函数
    不是每个程序员天生对递归理解深刻,刚入大一时候,当别人写出第一个求最大公约数的递归函数时,对其多么的惊叹,竟然可以不用循环,竟然代码可以这么简洁,确实递归在大多数情况下实......
  • Day23.2.递归
    Day23.2.递归1.定义自己调用自己递归结构包括:递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。递归体:什么时候需要调用自身方法2.例题 publicclass......
  • 正则表达式?!的理解
    上代码:      首先我们根据代码以及结果可以知晓,跟在“?!”后面的表达式表示的是“iamworkingnow”这一句,结果只保留了“有事晚点聊”,那么“?!”即......
  • 【Python】关于print()、sys.stdout、sys.stderr的一些理解
    print()方法的语法:print(*objects,sep='',end='\n',file=sys.stdout,flush=False)其中file=sys.stdout的意思是,print函数会将内容打印输出到标准输出流(即sys.......
  • 深入理解Java核心技术:写给Java工程师的干货笔记(基础篇)张洪亮著编程语言专业科技电子工
    深入理解Java核心技术:写给Java工程师的干货笔记(基础篇)张洪亮著编程语言专业科技电子工业出版   ......
  • 什么是Redis持久化,如何理解?
    其实redis就是一种高级的以键值对形式存储数据的数据库,而它的好处就是他可以支持数据的持久化,其实redis之所以会有这样的优点,主要是因为,redis的数据都是存放在内存中的,如......
  • Angular 模块封装概念常见的错误理解
    Angular以类似于ES模块的方式引入了模块封装的概念。它基本上意味着可声明的类型——组件、指令和管道——只能由在该模块内声明的组件使用。例如,如果我尝试使用下面的......
  • 对于async和await的使用方式、作用效果不怎么理解 ?没关系,初步看这篇就够了
    首先不是阻塞式的,asyncawait是通过csp的方式实现的无堆栈携程,await在编译的时候会把await后的代码转换成状态机的下一步【可以简单理解为await之前的代码是Task里面执......
  • 第一百一十六篇: JavaScript理解对象
    好家伙,本篇为《JS高级程序设计》第八章“对象、类与面向对象编程”学习笔记 1.关于对象ECMA-262将对象定义为一组属性的无序集合。严格来说,这意味着对象就是一组没有特......