【8】递归之经典题型总结

608564A16E7D652E882914E830EE4050(1)

📚博客主页:代码探秘者

✨专栏:《JavaSe》 其他更新ing…

❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️

🙏作者水平有限,欢迎各位大佬指点,相互学习进步!


img

文章目录

  • Java递归全面总结
    • 一、递归基础概念
    • 二、递归注意事项(⚠️重点)
    • 三、经典递归问题
      • 1. 阶乘计算
      • 2. 斐波那契数列(优化版)
      • 3. 汉诺塔问题
      • 4. 二叉树前序遍历
      • 5. 全排列问题
      • 6. 快速排序(分治递归)
      • 7. 反转字符串
      • 8. 最大公约数(欧几里得算法)
    • 四、递归问题解决通用模板:
    • 五、递归优化技巧
    • 六、递归应用场景
    • 七、递归思维训练建议

Java递归全面总结

一、递归基础概念

  1. 定义

    • 方法直接或间接调用自身的过程
    • 必须包含递归条件基线条件
  2. 核心要素

    • 递归条件(Recursive Case):方法继续调用自身的条件
    • 基线条件(Base Case):终止递归的条件
  3. 执行原理

    public void recursiveMethod(int n) {if (n <= 0) {  // 基线条件return;}System.out.println(n);recursiveMethod(n-1);  // 递归条件
    }
    
  4. 内存机制

    • 每次递归调用都会在栈内存中创建新的栈帧
    • 栈深度过大时会导致StackOverflowError(典型深度约5000-7000层)

二、递归注意事项(⚠️重点)

  1. 必须要有终止条件:否则无限递归导致栈溢出
  2. 递归深度控制:对于大数据量问题,考虑改用循环
  3. 重复计算问题:如斐波那契数列的朴素递归效率极低
  4. 空间复杂度:递归调用栈会消耗额外内存
  5. 尾递归优化:Java不支持自动优化,但可手动实现

三、经典递归问题

1. 阶乘计算

解题思路

  1. 基线条件:1的阶乘是1
  2. 递归关系:n! = n × (n-1)!
  3. 逐步拆解问题直到达到基线条件
/*** 计算n的阶乘* @param n 要计算阶乘的数字* @return n的阶乘结果*/
public static int factorial(int n) {// 基线条件:1的阶乘为1if (n == 1) return 1;// 递归条件:n! = n * (n-1)!return n * factorial(n - 1);
}
// 示例:factorial(5) → 120

2. 斐波那契数列(优化版)

解题思路

  1. 基线条件:F(0)=0,F(1)=1
  2. 递归关系:F(n) = F(n-1) + F(n-2)
  3. 使用备忘录避免重复计算
// 备忘录数组
static int[] memo = new int[100];public static int fibonacci(int n) {// 基线条件if (n <= 1) return n;// 检查是否已计算过if (memo[n] != 0) return memo[n];// 递归计算并存储结果memo[n] = fibonacci(n-1) + fibonacci(n-2);return memo[n];
}
// 示例:fibonacci(10) → 55

3. 汉诺塔问题

解题思路

  1. 将n个盘子从A移到C =
    • 先把n-1个从A移到B(借助C)
    • 移动第n个到C
    • 把n-1个从B移到C(借助A)
  2. 最小规模问题:1个盘子直接移动
public static void hanoi(int n, char from, char to, char aux) {// 基线条件:只剩一个盘子if (n == 1) {System.out.println("移动盘子 1 从 " + from + " 到 " + to);return;}// 将n-1个盘子移到辅助柱hanoi(n-1, from, aux, to);// 移动最下面的盘子System.out.println("移动盘子 " + n + " 从 " + from + " 到 " + to);// 将n-1个盘子移回目标柱hanoi(n-1, aux, to, from);
}
// 示例:hanoi(3, 'A', 'C', 'B')

4. 二叉树前序遍历

解题思路

  1. 访问根节点
  2. 递归遍历左子树
  3. 递归遍历右子树
  4. 基线条件:节点为null时返回
class TreeNode {int val;TreeNode left;TreeNode right;
}public static void preOrder(TreeNode root) {// 基线条件:空树if (root == null) return;// 1. 访问根节点System.out.print(root.val + " ");// 2. 递归遍历左子树preOrder(root.left);// 3. 递归遍历右子树preOrder(root.right);
}
// 示例输出:根 → 左 → 右

5. 全排列问题

解题思路

  1. 固定第一个位置,递归求后面所有排列
  2. 通过交换元素实现不同排列
  3. 基线条件:start到达数组末尾
public static void permute(int[] nums, int start) {// 基线条件:已处理完所有元素if (start == nums.length - 1) {System.out.println(Arrays.toString(nums));return;}for (int i = start; i < nums.length; i++) {// 交换元素到当前位置swap(nums, start, i);// 递归生成后续排列permute(nums, start + 1);// 恢复原始顺序(回溯)swap(nums, start, i);}
}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}
// 示例:permute([1,2,3], 0)

6. 快速排序(分治递归)

解题思路

  1. 选择基准元素(pivot)
  2. 将数组分为小于和大于基准的两部分
  3. 递归排序两个子数组
  4. 基线条件:数组长度<=1
public static void quickSort(int[] arr, int low, int high) {// 基线条件:子数组长度为0或1if (low < high) {// 获取分区点int pi = partition(arr, low, high);// 递归排序左半部分quickSort(arr, low, pi - 1);// 递归排序右半部分quickSort(arr, pi + 1, high);}
}private static int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = low - 1;for (int j = low; j < high; j++) {if (arr[j] < pivot) {i++;swap(arr, i, j);}}swap(arr, i + 1, high);return i + 1;
}
// 示例:quickSort(arr, 0, arr.length-1)

7. 反转字符串

解题思路

  1. 基线条件:空字符串或单字符
  2. 递归关系:reverse(s) = reverse(s.substring(1)) + s.charAt(0)
  3. 逐步将首字符移到末尾
public static String reverse(String s) {// 基线条件:空串或单字符if (s.isEmpty()) return s;// 递归反转:首字符放到最后return reverse(s.substring(1)) + s.charAt(0);
}
// 示例:reverse("hello") → "olleh"

8. 最大公约数(欧几里得算法)

解题思路

  1. 基线条件:b为0时返回a
  2. 递归关系:gcd(a,b) = gcd(b, a%b)
  3. 基于数学定理的优雅解法
public static int gcd(int a, int b) {// 基线条件:余数为0if (b == 0) return a;// 递归计算gcd(b, a mod b)return gcd(b, a % b);
}
// 示例:gcd(48, 18) → 6

四、递归问题解决通用模板:

  1. 定义基线条件:最简单情况直接返回结果
  2. 分解问题:将大问题拆解为相似小问题
  3. 递归调用:用更小规模参数调用自身
  4. 合并结果:将小问题的解组合成大问题的解

复杂度对比表

问题时间复杂度空间复杂度优化方法
阶乘O(n)O(n)尾递归改写
斐波那契O(2^n)→O(n)O(n)备忘录/动态规划
汉诺塔O(2^n)O(n)无(问题本质决定)
二叉树遍历O(n)O(h)莫里斯遍历
全排列O(n!)O(n)堆算法

注:实际开发中应优先考虑迭代解法,递归更适合表达清晰的算法逻辑。对于深度可能超过1000层的问题,建议使用栈模拟递归或改用动态规划。

五、递归优化技巧

  1. 备忘录法(记忆化搜索)

    // 斐波那契优化示例
    static int[] memo = new int[100];
    public static int fib(int n) {if (n <= 1) return n;if (memo[n] != 0) return memo[n];memo[n] = fib(n-1) + fib(n-2);return memo[n];
    }
    
  2. 尾递归改写

    // 阶乘的尾递归版本
    public static int factorialTail(int n, int accumulator) {if (n == 1) return accumulator;return factorialTail(n-1, n * accumulator);
    }
    
  3. 改迭代实现

    // 斐波那契迭代版
    

六、递归应用场景

  1. 树形结构操作:二叉树遍历、文件系统遍历
  2. 分治算法:归并排序、快速排序
  3. 回溯算法:八皇后问题、数独求解
  4. 动态规划:背包问题(记忆化搜索实现)
  5. 数学问题:组合计算、泰勒展开

七、递归思维训练建议

  1. 从简单案例入手(如阶乘、斐波那契)
  2. 画递归调用树理解执行流程
  3. 使用IDE调试功能观察调用栈变化
  4. 先写基线条件,再写递归条件
  5. 注意参数在递归过程中的变化规律

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/43022.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JC4010快速入门

目录 一、硬件接线二、软件操作2.1、 设置2.2、 零点 校准2.3、闭环控制2.4、调整PI参数2.5、切换控制模式 三、CAN模块操作3.1、使用CANable3.2、发送指令3.3、其它 一、硬件接线 ZH1.5-6P 和 SH1.0-3P 端子定义如下&#xff1a; 红色接电源正极&#xff0c;黑色接电源负极&a…

基于Spring Boot的高校普法系统的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

从零开始跑通3DGS教程:(三)坐标系与尺度编辑(CloudCompare)

写在前面 本文内容 本文所属《从零开始跑通3DGS教程》系列文章&#xff1b; sfm重建的点云已经丢掉了尺度信息&#xff0c;并且坐标系跟图像数据有关(SFM初始化选择的图像)&#xff0c;所以如果想恢复物理真实尺度&#xff0c;以及在想要的视角下渲染&#xff0c;那么需要对尺度…

代码随想录day31 贪心part05

56.合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;in…

【MyBatis】MyBatis 操作数据库(入门)

文章目录 前言一、什么是MyBatis&#xff1f;二、MyBatis入门2.1、准备工作2.1.1 创建工程2.1.2、数据准备 2.2、配置数据库连接字符串2.3、写持久层代码2.4 单元测试 三、MyBatis的基础操作3.1 打印日志3.2、参数传递3.3、增(Insert)3.4、 删(Delete)3.5、改(Update)3.6、查(S…

蓝桥杯备考:多米诺骨牌

这道题要求上下方格子和之差要最小&#xff0c;其实就是算每个上下格子的差求和的最小值 这道题其实是动态规划01背包问题 我们直接按步骤做吧 step1:定义状态表示f[i][j]表示从1到i个编号的差值里选出刚好j个数的最小操作次数 step2:推导状态转移方程 如图这就是我们的状态…

bluecode-20240913_1_数据解码

时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 256MB&#xff0c;其他语言 512MB 难度&#xff1a;困难 数据解码 指定有一段经过编码的二进制数据&#xff0c;数据由0个或多个"编码单元"组成。"编码单元"的编码方式…

day1_Flink基础

文章目录 Flink基础今日课程内容目标为什么要学Flink技术更新迭代市场需求 流式计算批量计算概念特点 批量计算的优势和弊端流式计算生活中流场景流式计算的概念 Flink简介Flink历史Flink介绍 Flink架构体系已学过的框架技术Flink架构 Flink集群搭建Flink的集群模式Standalone模…

集多功能为一体的软件,支持批量操作。

今天我给大家分享一个超实用的小工具&#xff0c;真的是太好用了&#xff01;这个软件是吾爱大神无知灰灰制作的&#xff0c;它能直接一键把webp格式的图片转换成png格式。 webp转为png 一键操作&#xff0c;支持压缩 其实&#xff0c;作者最近在工作中经常遇到webp格式的图片…

Linux 基本使用和 web 程序部署

目录 Linux 常用命令 ls cd 认识 Linux 目录结构 绝对路径 vs 相对路径 使用 tab 键补全 使用 ctrl c 重新输入 pwd touch cat echo vim 1) 创建文件 / 打开文件 ​编辑 2) 进入插入模式 3) 保存 4) 退出 mkdir rm mv cp man grep ps netstat 搭建 J…

CentOS 7 部署RuoYi 项目

换源 备份现有的 YUM 源配置文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 默认的 CentOS 官方镜像源替换为阿里云的镜像源&#xff0c;以提高下载速度和稳定性。 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.co…

【Kafka】分布式消息队列的核心奥秘

文章目录 一、Kafka 的基石概念​主题&#xff08;Topic&#xff09;​分区&#xff08;Partition&#xff09;​生产者&#xff08;Producer&#xff09;​消费者&#xff08;Consumer&#xff09;​ 二、Kafka 的架构探秘​Broker 集群​副本机制​ 三、Kafka 的卓越特性​高…

linux课程学习二——缓存

一.文件io与标准io的一个区别 遇到死循环可以ctrl c结束进程 使用printf输出&#xff0c;输出没有问题 用wirte输出&#xff0c;参数1&#xff0c;可以理解为上面介绍的linux标准文件描述符的1&#xff08;STDOUT&#xff09;标准输出&#xff0c;我们加上一个死循环while&…

【区块链安全 | 第九篇】基于Heimdall设计的智能合约反编译项目

文章目录 背景目的安装1、安装 Rust2、克隆 heimdall-dec3、编译 heimdall-dec4、运行 heimdall-dec 使用说明1、访问 Web 界面2、输入合约信息3、查看反编译结果 实战演示1、解析普通合约2、解析代理合约 背景 在区块链安全研究中&#xff0c;智能合约的审计和分析至关重要。…

CANoe入门——CANoe的诊断模块,调用CAPL进行uds诊断

目录 一、诊断窗口介绍 二、诊断数据库文件管理 三、添加基础诊断描述文件&#xff08;若没有CDD/ODX/PDX文件&#xff09;并使用对应的诊断功能进行UDS诊断 3.1、添加基础诊断描述文件 3.2、基于基础诊断&#xff0c;使用诊断控制台进行UDS诊断 3.2.1、生成基础诊断 3.…

关于embedding向量模型的知识

环境&#xff1a; embedding 问题描述&#xff1a; 关于embedding向量模型的知识 解决方案&#xff1a; 向量模型基础 定义与本质&#xff1a;embedding向量模型是一种将离散数据&#xff08;如文本、图像、用户行为等&#xff09;映射到连续向量空间的技术。其核心思想是…

Docker远程访问与加密配置指南

实验目的 基础功能验证&#xff1a; 验证Docker远程访问的基础配置方法 测试未加密(2375端口)和TLS加密(2376端口)两种连接方式的可用性安全性对比&#xff1a; 对比防火墙开启/关闭状态下系统的暴露风险 分析未加密通信的数据传输安全性 验证TLS证书认证机制的有效性操作实践…

基于 Python 深度学习 lstm 算法的电影评论情感分析可视化系统(2.0 系统全新升级,已获高分通过)

大家好&#xff0c;欢迎来到我的技术专栏&#xff01;今天我将和大家聊聊如何利用 Python 的深度学习技术&#xff0c;打造一个集电影评论情感分析与可视化展示于一体的系统。这个系统不仅能自动采集和解析海量影评&#xff0c;还能实时生成直观的情感趋势图表&#xff0c;对于…

pytorch中dataloader自定义数据集

前言 在深度学习中我们需要使用自己的数据集做训练&#xff0c;因此需要将自定义的数据和标签加载到pytorch里面的dataloader里&#xff0c;也就是自实现一个dataloader。 数据集处理 以花卉识别项目为例&#xff0c;我们分别做出图片的训练集和测试集&#xff0c;训练集的标…

业之峰与宏图智能战略携手,开启家装数字化新篇章

3月8日&#xff0c;业之峰装饰集团董事长张钧携高管团队与宏图智能董事长庭治宏及核心团队&#xff0c;在业之峰总部隆重举行了战略合作签约仪式&#xff0c;标志着双方将携手探索业之峰的数字化转型之路&#xff0c;共同推动家装行业的变革与发展。 近年来&#xff0c;家装行业…