数据结构与算法(六):递归
一、什么是递归#
所谓递归,简单点来说,就是一个函数直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
引用知乎大佬的例子:
我们可以把” 递归 “比喻成 “查字典 “,当你查一个词,发现这个词的解释中某个词仍然不懂,于是你开始查这第二个词。
可惜,第二个词里仍然有不懂的词,于是查第三个词,这样查下去,直到有一个词的解释是你完全能看懂的,那么递归走到了尽头,然后你开始后退,逐个明白之前查过的每一个词,最终,你明白了最开始那个词的意思。
我们把查字典理解成一个函数search(){}
,而“明白了”就是停止条件。
按这个思路,那这个流程就是这样的:
public void search(){
//如果明白了就停止函数
if("明白了"){
return;
}
//没明白调用自己继续查
search();
}
我们举个简单的例子:
要计算阶乘1*2*3*.....*(n-1)*n
,代码如下:
public static int mult(int n) {
//终止条件,当n=1时直接返回1
if (n == 1){
return n;
}
//计算n*(n-1).....
return n * mult(n - 1);
}
二、递归和栈的关系#
递归的过程就是出入栈的过程
递归的问题实际上都能拆分成出入栈问题,我们可以举上面计算1*2*3*.....*(n-1)*n
这个例子来理解一下:
如果n=4,那么过程就是这样:
- mult(4)调用了mult(3)
- mult(3)调用了mult(2)
- mult(2)调用了mult(1)
- 到了mult(1)时满足了终止条件,返回结果
用出入栈的思维理解:
- 步骤1-3都是一个入栈过程,mult(4)计算得出结果后入栈,然后运行mult(3)得出结果,然后在入栈......以此类推
- 当到达n=1的停止条件时递归停止不再入栈,此时栈深度就是4,这也叫递归深度
- 满足停止条件后出栈,mult(1)的结果出栈,与mult(2)的结果出栈相乘,再与随后出栈的mult(3)的结果相乘.....以此类推
递归的本质就是栈的出入过程,所以实际上当深度过深,超过了jvm规定允许的栈最大深度的时候,就会出现栈溢出的问题,也就是java里的StackOverflowError
三、递归的使用条件#
那么,我们是时候可以使用递归来解决问题呢:
- 当问题可以拆分为子问题,并且子问题与原问题解决方法相同
- 有一个明确的程序停止条件
比如之前的文章中提到连续乘除问题就是一个典型的例子。
作者:Createsequence
出处:https://www.cnblogs.com/Createsequence/p/13195751.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义