递归思想

有一天,寺院的僧人们开始研究这个汉诺塔的问题,由于64个大铁盘子实在是太多了,住持一时之间也无从下手。

于是他出了一个主意,先假设现在的盘子数量是4个,三根柱子分别为A,B,C,目标是将A柱子上的4个盘子移动到C上。僧人们松了一口气,解决这个4阶的汉诺塔移动问题总比64阶要简单些。

首先聪明的僧人A想到了,将A柱子最顶上的3个盘子移动到B上,接着将A柱子最底下最大的盘子挪到C上,最后再将B柱子上的所有盘子挪到C上。

  1. 盘子123,从A到B
  2. 盘子4,从A到C
  3. 盘子123,从B到C

众人纷纷夸奖僧人A,但是现在又出现了两个问题。怎么将A柱子最顶上的3个盘子挪到B上呢?怎么最后将B上的盘子挪到C上呢?(相当于解决一个3阶的从A柱挪到B柱的汉诺塔问题)

针对第一个问题,这时候僧人B站了出来,他说,请大家忽略盘子4,将A柱子上最顶上的2个盘子挪到C上,将A柱子最底下最大的盘子3挪到B,最后再将C柱子上所有盘子挪到B上。

  1. 盘子12,从A到C
  2. 盘子3,从A到B
  3. 盘子12,从C到B

那么现在问题又来了,怎么将A柱子最顶上的2个盘子挪到C上呢?僧人C发表了他的意见,请大家不要考虑盘子3,将A柱子上最顶上的1个盘子挪到B上,将A柱子最底下最大的盘子2挪到C,最后再将B柱子上所有盘子挪到C上。(相当于解决一个2阶的从A柱挪到C柱的汉诺塔问题)

  1. 盘子1,从A到B
  2. 盘子2,从A到C
  3. 盘子1,从B到C

至此,可以看出,每一个大问题被分解成三个步骤(小问题),而每一个小问题又分成三个步骤。从每层问题的相似性得出了一个规律,在每层问题第一个步骤里,当挪动n-1个盘子时,B柱会跟C柱产生调换的情况(相当于一个n-1阶的从A柱到B柱的汉诺塔问题),同理,在每层问题第三个步骤里,当挪动n-1个盘子时,B柱会跟A柱产生调换的情况(相当于一个n-1阶的从B柱到C柱的汉诺塔问题)。

个人理解,递归的思想,就是将一个大问题分解成许多层小问题,每层之间遵循一定的规律性,每次只解决当前层的问题,其余问题交给下一层的人去解决,逐层下去,最终在最后一个人手上得到最终答案。

 

递归问题:使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

尾递归优化:

尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。

遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

posted @   heartbeat111  阅读(124)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示