GESP5级C++考试语法知识(十二、递归算法(二))


🌟 第一章:递归复杂度如何计算("分身术小精灵")

1、🎯 故事:

递归小精灵有一个技能:

👉 可以"分身"去解决子问题!


2、但问题来了:

  • 有的精灵:只分出1个分身 😌

  • 有的精灵:分出2个 😮

  • 有的精灵:分出3个甚至更多 😱


3、👉 分身越多,工作量就会爆炸增长!


🌟 第二章:递归复杂度的核心公式

1、判断递归复杂度,最关键看这个:

复制代码
T(n) = a * T(n/b) + f(n)

2、👉 这是经典模型(分治思想)


3、🧠 各个参数含义:

符号 含义
a 每次分成几个子问题
n/b 每个子问题规模
f(n) 当前层做的工作

4、👉 简单记:

💡 "分几叉(a) + 深度多少(log n)"


🌟 第三章:三种经典递归类型对比🔥


🎯 类型1:一条链(最简单)

1、示例:求阶乘

复制代码
int f(int n)
{
    if(n == 1) return 1;
    return n * f(n-1);
}

2、🌲 递归树

复制代码
f(n)
 ↓
f(n-1)
 ↓
f(n-2)
 ↓
...

3、🧠 分析:

  • 每次只调用 1 个子问题 👉 a = 1

  • 深度:n

👉 总次数:

复制代码
O(n)

4、🎯 结论:

👉 单链递归 = O(n)


🎯 类型2:二叉爆炸(很危险🔥)

1、示例:斐波那契

复制代码
int f(int n)
{
    if(n <= 2) return 1;
    return f(n-1) + f(n-2);
}

2、🌲 递归树

复制代码
        f(n)
       /   \
   f(n-1) f(n-2)
   /   \      ...

3、🧠 分析:

  • 每次分成 2 个 👉 a = 2

  • 深度:n

👉 节点数 ≈

复制代码
O(2^n)

💥 指数爆炸!


4、🎯 结论:

👉 多叉递归 + 无优化 = 指数复杂度


🎯 类型3:分治递归(高效)

1、示例:归并排序

复制代码
void merge_sort(int l, int r)
{
    if(l >= r) return;

    int mid = (l + r) / 2;

    merge_sort(l, mid);
    merge_sort(mid+1, r);

    merge(); // 合并
}

2、🌲 递归树(关键!)

复制代码
层1: n
层2: n
层3: n
...

👉 每一层工作量都是 n!


3、🧠 分析:

  • 分成2个问题 👉 a = 2

  • 每个规模 n/2 👉 b = 2

  • 层数:log n

  • 每层:O(n)

👉 总:

复制代码
O(n log n)

🌟 第四章:为什么差距这么大?

1、🎯 核心原因:

👉 有没有"重复计算"!


2、❌ 斐波那契:

  • f(3) 被算很多次 ❌

  • 浪费大量时间 ❌

👉 指数级


3、✅ 归并排序:

  • 每个子问题只算一次 ✅

  • 没有重复 ✅

👉 n log n


🌟 第五章:万能判断方法(考试必会🔥)


🎯 方法1:画递归树(最推荐)


步骤:

1️⃣ 看分几叉(a)

  • 1个 👉 线性

  • 2个 👉 小心爆炸


2️⃣ 看深度

  • 每次减1 👉 深度 n

  • 每次减半 👉 深度 log n


3️⃣ 估算总节点数


🎯 快速口诀:

复制代码
链式 → O(n)
二叉爆炸 → O(2^n)
分治 → O(n log n)

🎯 方法2:看是否有重复子问题


1、👉 问自己:

❓ "这个子问题会不会被重复算?"


2、判断:

情况 复杂度
有大量重复 指数级
无重复 多项式级

🎯 方法3:看是否可以记忆化


👉 如果可以记忆化:

👉 复杂度通常可以优化为:

复制代码
指数 → 线性 

🌟 第六章:几个经典对比🔥


1、🎯 对比1:斐波那契

方法 复杂度
递归 O(2^n)
递归+记忆化 O(n)
递推 O(n)

2、🎯 对比2:DFS搜索

(1)👉 最坏:

复制代码
O(分支数^深度)

(2)比如:

  • 每步4个方向

  • 走10步


(3)👉

复制代码
O(4^10)

🌟 第七章:一眼判断技巧(非常重要🔥)


🎯 快速判断表

特征 复杂度
每次调用1个 O(n)
每次调用2个(无缓存) O(2^n)
每次减半 O(log n)
分治 + 合并 O(n log n)

🌟 最终总结


1、🎯 本质一句话:

👉 递归复杂度 = 分支数 × 深度


2、🎯 更精准一点:

👉 递归树节点总数


3、🎯 最重要的判断:

复制代码
有没有重复计算?!

接下来,我们进行🌟《递归王国闯关大冒险》🌟


🏰 第1关:小兔子爬楼梯(基础递归)

1、🎯 故事

小兔子要跳到第 n 阶楼梯

每次可以跳 1 阶 或 2 阶

👉 问:一共有多少种跳法?


2、🧠 思路(递归)

(1)第 n 阶的方法:

  • 从 n-1 跳一步

  • 从 n-2 跳两步


(2)👉 所以:

复制代码
f(n) = f(n-1) + f(n-2)

3、✅ C++代码

复制代码
#include <iostream>
using namespace std;

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

int main()
{
    int n;
    cin >> n;
    cout << f(n);
}

4、⏱ 时间复杂度

👉 每次分成 2 个递归!

像一棵树:

cpp 复制代码
        f(n)
      /      \
  f(n-1)   f(n-2)
   /   \      /   \
...

👉 节点数 ≈ 2^n

时间复杂度:O(2^n)(指数爆炸💥)


5、🧠 空间复杂度

👉 最深一路:n → n-1 → n-2 → ... → 1

空间复杂度:O(n)


🏰 第2关:数字拆分(打印每一位)

1、🎯 故事

魔法数字 1234 被锁住了

需要一位一位从高到低念出来!


2、🧠 思路

递归思路:

👉 先处理前面,再处理最后一位

复制代码
print(n/10)
输出 n%10

3、✅ C++代码

复制代码
#include <iostream>
using namespace std;

void print(int n)
{
    if(n == 0) return;

    print(n / 10);
    cout << n % 10 << " ";
}

int main()
{
    int n;
    cin >> n;
    print(n);
}

4、⏱ 时间复杂度

(1)👉 每次去掉一位

比如:

cpp 复制代码
1234 → 123 → 12 → 1

👉 共 d 次(位数)


(2)✅ 时间复杂度:O(d)

👉 d ≈ log₁₀(n)

👉 所以:

O(log n)


5、🧠 空间复杂度

👉 递归深度 = 位数

O(log n)


🏰 第3关:阶乘魔法

1、🎯 故事

魔法师说:

复制代码
n! = n × (n-1)!

2、🧠 思路

递归公式:

复制代码
f(n) = n * f(n-1)

边界:

复制代码
f(1) = 1

3、✅ C++代码

复制代码
#include <iostream>
using namespace std;

int f(int n)
{
    if(n == 1) return 1;
    return n * f(n-1);
}

int main()
{
    int n;
    cin >> n;
    cout << f(n);
}

4、⏱ 时间复杂度

(1)👉 每次只调用 1 次

cpp 复制代码
n → n-1 → n-2 → ... → 1

(2)👉 共 n 次

时间复杂度:O(n)


5、🧠 空间复杂度

👉 深度 = n

O(n)


🏰 第4关:字符串反转

1、🎯 故事

(1)一段咒语:

复制代码
HELLO

(2)需要倒着念:

复制代码
OLLEH

2、🧠 思路

👉 先递归后面的,再输出当前字符


3、✅ C++代码

复制代码
#include <iostream>
using namespace std;

void rev(string s, int i)
{
    if(i == s.size()) return;

    rev(s, i + 1);
    cout << s[i];
}

int main()
{
    string s;
    cin >> s;
    rev(s, 0);
}

4、⏱ 时间复杂度

👉 每个字符访问一次

字符串长度 = n

时间复杂度:O(n)


5、🧠 空间复杂度

👉 递归深度 = n

O(n)


🏰 第5关:汉诺塔(经典递归🔥)

1、🎯 故事

3根柱子,要把盘子从 A 移到 C

规则:

  • 每次只能移动一个

  • 大的不能压小的


2、🧠 思路

核心递归:

1️⃣ 把 n-1 从 A → B

2️⃣ 把第 n 个 A → C

3️⃣ 把 n-1 从 B → C


3、✅ C++代码

复制代码
#include <iostream>
using namespace std;

void hanoi(int n, char A, char B, char C)
{
    if(n == 1)
    {
        cout << A << "->" << C << endl;
        return;
    }

    hanoi(n-1, A, C, B);
    cout << A << "->" << C << endl;
    hanoi(n-1, B, A, C);
}

int main()
{
    int n;
    cin >> n;
    hanoi(n, 'A', 'B', 'C');
}

4、⏱ 时间复杂度

(1)递推式:

cpp 复制代码
T(n) = 2*T(n-1) + 1

(2)展开:

cpp 复制代码
T(n) = 2^n - 1

(3)✅ 时间复杂度:O(2^n)

👉 超级费时间!


5、🧠 空间复杂度

👉 最大深度 = n

O(n)


🏰 第6关:斐波那契(递归效率陷阱)

1、🎯 故事

兔子繁殖:

复制代码
1 1 2 3 5 8 ...

2、🧠 思路

复制代码
f(n) = f(n-1) + f(n-2)

⚠️ 会重复计算!


3、✅ 递归版本(慢)

复制代码
int f(int n)
{
    if(n <= 2) return 1;
    return f(n-1) + f(n-2);
}

4、🚀 优化(记忆化)

复制代码
#include <iostream>
using namespace std;

int dp[1000];

int f(int n)
{
    if(n <= 2) return 1;
    if(dp[n]) return dp[n];

    return dp[n] = f(n-1) + f(n-2);
}

int main()
{
    int n;
    cin >> n;
    cout << f(n);
}

5、❌ 普通递归

⏱ 时间复杂度

同第1关:

O(2^n)


6、🚀 记忆化版本

👉 每个 f(n) 只算一次!

⏱ 时间复杂度

👉 一共 n 个状态

O(n)


7、🧠 空间复杂度

👉 dp数组 + 递归深度

O(n)


🎉 总结

这 6 关在训练你:

关卡 能力
1 递推关系
2 拆分问题
3 数学递归
4 顺序控制
5 经典递归模型
6 复杂度优化

相关推荐
AI科技星8 分钟前
精细结构常数α的几何本源:从第一性原理的求导证明、量纲分析与全域验证
算法·机器学习·数学建模·数据挖掘·量子计算
6Hzlia14 分钟前
【Hot 100 刷题计划】 LeetCode 287. 寻找重复数 | C++ 数组判环 (快慢指针终极解法)
c++·算法·leetcode
MegaDataFlowers14 分钟前
26.删除有序数组中的重复项
算法
Robot_Nav1 小时前
DPMPC-Planner:复杂静态环境与动态障碍物下的无人机实时轨迹规划框架
c++·无人机·mpc
故事和你912 小时前
洛谷-数据结构1-4-图的基本应用2
开发语言·数据结构·算法·深度优先·动态规划·图论
吴可可1232 小时前
C#合并首尾相连多段线实战
算法·c#
KMDxiaozuanfeng2 小时前
卡梅德生物技术快报|SPR 技术应用|基于 SPR 亲和力的中药活性成分筛选系统实现与数据分析
科技·算法·面试·考试
水饺编程3 小时前
第5章,[标签 Win32] :获取设备环境的信息
c语言·c++·windows·visual studio
lhbian3 小时前
C++、C与易语言:编程语言对比解析
c语言·开发语言·c++
꧁细听勿语情꧂3 小时前
数据结构概念和算法、时间复杂度、空间复杂度引入
c语言·开发语言·数据结构·算法