跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

递归算法:原理、设计与经典例题解析

递归算法通过函数调用自身解决可分解为相同结构子问题的情形。设计关键在于确定子问题共性、构建函数头及设定递归出口。文中结合汉诺塔、合并有序链表、反转链表及快速幂等案例,阐述了递归逻辑与 C++ 实现细节,解析了递归执行从底向上返回的过程。

狂少发布于 2026/3/27更新于 2026/10/2590 浏览
递归算法:原理、设计与经典例题解析

什么是递归

递归的本质是通过函数调用自身来实现问题的求解。其代码通常较为简洁,设计递归需遵循以下步骤:

  1. 确定问题可被分解为多个重复子问题,且子问题具有与原问题相同的解决方法。
  2. 提取子问题的共同点,从宏观角度看待问题。
  3. 构建函数头,明确函数解决的问题。
  4. 思考递归的出口(终止条件)。递归出口是必须的,且在执行过程中一定会触发。

简单来说,当一个问题可以不断分化成小问题时,即可使用递归算法。

具体例题讲解

LeetCode 面试题 08.06. 汉诺塔问题

题目要求借助 B 柱子将 A 上的盘子移动到 C 上。

文章配图

观察不同数量的盘子情况:

  • 1 个盘子:直接从 A 移到 C。
  • 2 个盘子:借助 C 将 A 上盘子移至 B,将 A 最大盘移至 C,再将 B 上盘子移至 C。
  • 3 个盘子及以上:同理,通过中间柱子转移 n-1 个盘子。

递归出口:当 A 或 B 上只有一个盘子时,直接将其放到 C 并返回。

class Solution {
public:
    void dfs(vector<int>& x, vector<int>& y, vector<int>& z, int n) {
        if (n == 1) {
            z.push_back(x.back());
            x.pop_back();
            return;
        }
        dfs(x, z, y, n - 1);
        z.push_back(x.back());
        x.pop_back();
        dfs(y, x, z, n - 1);
    }
    void hanota(vector<int>& a, vector<int>& b, vector<int>& c) {
        (a, b, c, a.());
    }
};
dfs
size

注意:递归出口通常写在最前面,防止死循环。

LeetCode 21. 合并两个有序链表

题目要求将两个有序链表合并为一个,不可再生成新链表。

文章配图

直接在原函数中递归:

  • 出口:当一个链表为空时,返回另一个链表。
  • 逻辑:比较两链表当前节点值,较小者作为当前节点,其 next 指向剩余部分的递归结果。
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (!l1) return l2;
        if (!l2) return l1;
        if (l1->val <= l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        } else {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }
};

LeetCode 206. 反转链表

题目要求翻转链表。解法包括递归和三指针。

文章配图

递归实现:

  • 函数头表示当前需要反转的节点。
  • 出口:遇到最后节点或空节点时返回。
  • 单链表需提前保存最后一个节点位置(newnode)。
  • 逻辑:当前节点的下一个节点指向当前节点,当前节点指向空。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* dfs(ListNode* l1) {
        if (!l1 || !l1->next) return l1;
        ListNode* newnode = dfs(l1->next);
        l1->next->next = l1;
        l1->next = nullptr;
        return newnode;
    }
    ListNode* reverseList(ListNode* head) {
        return dfs(head);
    }
};

LeetCode 50. Pow(x, n)

手动实现 pow 函数。n 可能为负数或很大,需注意处理。

文章配图

发现重复子问题:2 的 16 次方可由两个 2 的 8 次方相乘得到。

文章配图

代码实现:

  • m 赋值给 long long 类型以防溢出。
  • 若 m 为负数,x=1/x,n 转为正数。
  • 递归计算 n/2 次幂,根据奇偶性返回结果。
class Solution {
public:
    double myPow(double x, int m) {
        long long n = m;
        if (n < 0) {
            x = 1 / x;
            n = -n;
        }
        if (n == 0) return 1.0;
        double tmp = myPow(x, n / 2);
        if (n % 2 == 0) {
            return tmp * tmp;
        } else {
            return tmp * tmp * x;
        }
    }
};

总结

学习递归算法需理解'自己调用自己'的过程。递归执行是从底向上返回,存在从小到大、从后到前的过程。若难以理解,建议绘制递归展开图辅助分析。

目录

  1. LeetCode 面试题 08.06. 汉诺塔问题
  2. LeetCode 21. 合并两个有序链表
  3. LeetCode 206. 反转链表
  4. LeetCode 50. Pow(x, n)

更多推荐文章

查看全部
  • 前端响应式布局实现方案
  • LazyLLM 多 Agent 应用实战:源码部署与 Web 调试全链路
  • VS Code 前端开发必备插件指南:10 款效率工具与配置详解
  • 腾讯混元大模型业务落地实践与技术方案
  • 利用 Claw Cloud Run 免费部署前端网页
  • 如何用ChatGPT降低毕业论文的AIGC重复率?(最新版详细攻略)
  • Socket 标准参数详解:BACKLOG、KEEPALIVE 与 TCP_NODELAY
  • 深度学习训练流程拆解:从数据到参数更新
  • Prompt 驱动的结构化抽取:从非结构化文本高效提取表格
  • AI 写作实战项目:自动写作助手设计与实现
  • 普通产品经理转型 AI 产品经理的准备与能力要求
  • AG-UI:构建 AI 前端交互的统一协议
  • 程序员副业赚钱的九种途径与实战建议
  • LayerNorm 与 RMSNorm 深度解析:大模型为何转向 RMSNorm
  • Stable Diffusion 插件开发:低成本远程调试指南
  • C++ 继承机制详解:栈实现、名称隐藏与默认成员函数
  • Apache 2.2 部署 ASP.NET 3.5 实战配置指南
  • 量化、算子融合、内存映射:C语言实现AI推理的三板斧
  • JSP 高速公路管理系统设计与实现
  • LLaMA 网络架构深度解析

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online