数据结构与算法之美【8】-递归算法

本文介绍了递归的基本概念,分析了使用递归解决问题的三个关键条件,并通过一个具体实例详细展示了如何实现递归代码,包括如何寻找递推公式、终止条件及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、概述

二、示例分析

三、小结


一、概述

递归严格说起来不算一种算法,只能说是一种问题处理思想或者问题处理技巧。只要问题同时满足以下三个条件,就可以考虑用递归来解决:

  1. 一个问题的解可以分解为几个子问题的解
  2.  这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
  3.  存在递归终止条件

个人觉得,写递归代码最关键的是写出递推公式,找到终止条件,找到如何将大问题分解为小问题的规律,并且基于此写出递推公式,然后再推敲终止条件,最后将递推公式和终止条件翻译成代码。不用想一层层的调用关系,不要试图用人脑去分解递归的每个步骤。

二、示例分析

下面举一个例子,然后一步一步实现一个递归代码,帮你理解递归思想:

假如这里有 n 个台阶,每次你可以跨 1 个台阶或者 2 个台阶,请问走这 n 个台阶有多少种走法?

解析:

我们先假设n个台阶有x个走法,即x = f(n)。

对于第一步,我们有两种走法:

  1. 走1个台阶,剩余n-1个台阶。
  2. 走2个台阶,剩余n-2个台阶。

所以由此我们可以推导出f(n)=f(n-1) + f(n-2),递归格式我们已经推导出来了,下面我们再来分析一下终止条件:

随着我们不同走法,最后台阶要么剩下1个,要么剩下2个,如果是1个,很简单,下一步只能走1个台阶,即f(1)=1。如果剩余2个台阶,下一步我们有两个选择,即一次走两个台阶和两次每次走1个台阶,即f(2) = 2。

综上,递推公式为f(n) = f(n-1) + f(n-2)。

终止条件为:f(1) = 1或者f(2) = 2

 有了递推公式和终止条件,我们就可以以此写出代码了,但在写递归代码时候,需要注意以下两点:

  1. 警惕堆栈溢出,如果递归求解的数据规模很大,调用层次很深,一直压入栈,就会有堆栈溢出的风险。可以通过在代码中限制递归调用的最大深度的方式来解决这个问题。
  2. 要警惕重复计算,可以通过一个数据结构(比如散列表)来保存已经求解过的 f(k)。
  3. 函数调用耗时多、空间复杂度高

参考代码如下:

int f(int n) {
    if (1 == n||0 == n) {
        return 1;
    } else {
        return (f(n - 1) + f(n - 2));
    }
}

三、小结

递归是一种非常高效、简洁的编码技巧。只要是满足“三个条件”的问题就可以通过递归代码来解决。编写递归代码的关键就是正确姿势是写出递推公式,找出终止条件,然后再翻译成递归代码。递归代码虽然简洁高效,但是,递归代码也有很多弊端。比如,堆栈溢出、重复计算、函数调用耗时多、空间复杂度高等,所以,在编写递归代码的时候,一定要控制好这些副作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiang木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值