递归思想
有一天,寺院的僧人们开始研究这个汉诺塔的问题,由于64个大铁盘子实在是太多了,住持一时之间也无从下手。
于是他出了一个主意,先假设现在的盘子数量是4个,三根柱子分别为A,B,C,目标是将A柱子上的4个盘子移动到C上。僧人们松了一口气,解决这个4阶的汉诺塔移动问题总比64阶要简单些。
首先聪明的僧人A想到了,将A柱子最顶上的3个盘子移动到B上,接着将A柱子最底下最大的盘子挪到C上,最后再将B柱子上的所有盘子挪到C上。
- 盘子123,从A到B
- 盘子4,从A到C
- 盘子123,从B到C
众人纷纷夸奖僧人A,但是现在又出现了两个问题。怎么将A柱子最顶上的3个盘子挪到B上呢?怎么最后将B上的盘子挪到C上呢?(相当于解决一个3阶的从A柱挪到B柱的汉诺塔问题)
针对第一个问题,这时候僧人B站了出来,他说,请大家忽略盘子4,将A柱子上最顶上的2个盘子挪到C上,将A柱子最底下最大的盘子3挪到B,最后再将C柱子上所有盘子挪到B上。
- 盘子12,从A到C
- 盘子3,从A到B
- 盘子12,从C到B
那么现在问题又来了,怎么将A柱子最顶上的2个盘子挪到C上呢?僧人C发表了他的意见,请大家不要考虑盘子3,将A柱子上最顶上的1个盘子挪到B上,将A柱子最底下最大的盘子2挪到C,最后再将B柱子上所有盘子挪到C上。(相当于解决一个2阶的从A柱挪到C柱的汉诺塔问题)
- 盘子1,从A到B
- 盘子2,从A到C
- 盘子1,从B到C
至此,可以看出,每一个大问题被分解成三个步骤(小问题),而每一个小问题又分成三个步骤。从每层问题的相似性得出了一个规律,在每层问题第一个步骤里,当挪动n-1个盘子时,B柱会跟C柱产生调换的情况(相当于一个n-1阶的从A柱到B柱的汉诺塔问题),同理,在每层问题第三个步骤里,当挪动n-1个盘子时,B柱会跟A柱产生调换的情况(相当于一个n-1阶的从B柱到C柱的汉诺塔问题)。
个人理解,递归的思想,就是将一个大问题分解成许多层小问题,每层之间遵循一定的规律性,每次只解决当前层的问题,其余问题交给下一层的人去解决,逐层下去,最终在最后一个人手上得到最终答案。
递归问题:使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
尾递归优化:
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。
遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)
函数改成尾递归方式,也会导致栈溢出。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?