一文读懂 Java 递归,你不得不会的技能

news/2024/12/28 11:24:19/

Java递归是指在方法的执行过程中,通过调用自身的方式来实现重复执行一段代码的机制。它是一种非常有用的编程技术,特别是在处理树形数据结构或者分治算法时,递归能够简化代码实现,并使代码更易于理解和维护。

一、递归的基本原理

1.递归的定义:在计算机科学和数学中,递归是指一个函数调用自身的过程。递归函数通常包含两个部分:递归终止条件和递归工作。

2.递归的特点:递归不同于循环的地方在于它需要定义递归终止条件。递归函数必须要有终止条件,否则会出现无限递归,导致程序崩溃。

3.递归的优点:递归的主要优点是可以大大减少代码量,使代码更加清晰易懂,对于某些应用领域(如树、图等)来说,递归也是一种自然而然的表达方式,非常有利于程序的实现和简化。

二、递归的实现方式

  1. 递归方法实现

递归方法是一种最为常见的递归实现方式,它使用方法内嵌调用的方式来实现递归。在递归方法中,需要定义递归终止条件和递归工作。

递归终止条件:当满足某个条件时,递归就不再执行,否则递归将一直执行下去,导致程序崩溃。因此,在递归方法中必须设定递归终止条件来保证程序的正常运行。

递归工作:当递归没有满足终止条件时,递归会不断调用自身,直到满足终止条件为止。在递归方法中,递归工作通常包括重新调用方法本身并传入参数以及处理递归结果的过程。

例如:

public int factorial(int n) {if (n == 0) { // 终止条件return 1;} else { // 递归工作return n * factorial(n - 1);}
}

上述递归方法实现了n的阶乘计算,当n等于0时,递归终止条件满足,返回1。否则,递归调用本身,参数为n-1,处理递归结果n * factorial(n - 1)。

  1. 递归函数实现

递归函数实际上是通过对象引用的方式来实现递归的。使用递归函数时,需要定义一个对象,然后通过这个对象的引用来调用递归函数。在递归函数中,同样需要设定递归终止条件和递归工作。

例如:

public class Factorial {public int calculate(int n) {if (n == 0) { // 终止条件return 1;} else { // 递归工作Factorial fact = new Factorial();int result = fact.calculate(n - 1);return n * result;}}
}

上述递归函数同样实现了n的阶乘计算,当n等于0时,递归终止条件满足,返回1。否则,创建Factorial对象,调用calculate方法并传入参数n-1,处理递归结果n * result。

  1. 尾递归优化

尾递归可以使得递归变成循环,从而避免栈溢出以及提高执行效率。尾递归是指递归函数的最后一个操作是调用自身。

例如:

public int factorial(int n, int res) {if (n == 0) {return res;} else {return factorial(n - 1, n * res);}
}

上述尾递归方法实现了n的阶乘计算,每次递归时将当前结果乘以n,并将n-1作为新的参数传入下一次递归。当递归到n=0时,返回当前结果。

三、递归的优缺点

递归的优点:

  1. 代码简单清晰,易于理解和维护。

  2. 在处理树形数据结构或者分治算法时,递归能够使得代码更易于实现和清晰易懂。

  3. 递归可以大大减少代码量,提高编码效率。

递归的缺点:

  1. 调用递归方法会占用大量的系统栈空间,如果递归次数过多,将导致堆栈溢出。

  2. 递归执行效率相对较低,因为每次递归都需要创建新的堆栈帧,对于大数量级的数据处理,递归性能不如迭代。

  3. 对于某些问题,递归可能会增加代码复杂度,难以理解和维护。

四、递归的场景示例

  1. 斐波那契数列

斐波那契数列是指这样一个数列:0、1、1、2、3、5、8、13、21、34、……,在数学上,斐波那契数列以如下被以递推的方法定义:

F(0) = 0, F(1) = 1
F(n) = F(n-1) + F(n-2) (n>=2)

Java代码实现:

public int fibonacci(int n) {if(n == 0 || n == 1) { // 终止条件return n;} else { // 递归工作return fibonacci(n-1) + fibonacci(n-2);}
}
  1. 判断回文字符串

回文字符串是指正序和倒序相同的字符串,例如 “level”、“racecar” 就是回文字符串。

Java代码实现:

public boolean isPalindrome(String s) {if(s == null || s.length() == 0 || s.length() == 1) { // 终止条件return true;}char first = s.charAt(0);char last = s.charAt(s.length()-1);if(first != last) {return false;} else { // 递归工作return isPalindrome(s.substring(1, s.length()-1));}
}
  1. 走迷宫

给定一个矩阵,其中 0 表示通路,1 表示障碍,从左上角出发到右下角,问是否存在一条路径能够走到终点。

Java代码实现:

public boolean maze(int[][] matrix, int x, int y) {if(x<0 || x>=matrix.length || y<0 || y>=matrix[0].length) { // 判断越界return false;}if(matrix[x][y] == 1) { // 判断是否有障碍return false;}if(x == matrix.length-1 && y == matrix[0].length-1) { // 终止条件return true;}matrix[x][y] = 1; // 将当前节点标记为已走过if(maze(matrix, x-1, y) || maze(matrix, x+1, y)|| maze(matrix, x, y-1) || maze(matrix, x, y+1)) { // 递归工作return true;}matrix[x][y] = 0; // 如果无法找到合适的路径,取消标记return false;
}
  1. 组合问题

从 n 个元素中选 k 个元素的所有组合方式。

Java代码实现:

public List<List<Integer>> combine(int n, int k) {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();dfs(n, k, 1, path, res);return res;
}private void dfs(int n, int k, int start, List<Integer> path, List<List<Integer>> res) {if(path.size() == k) { // 终止条件res.add(new ArrayList<>(path));return;}for(int i=start; i<=n; i++) { // 递归工作path.add(i);dfs(n, k, i+1, path, res);path.remove(path.size()-1);}
}

http://www.ppmy.cn/news/92231.html

相关文章

2023电工杯B题全保姆教程及代码 人工智能对大学生学习影响的评价

A题&#xff1a;人工智能对大学生学习影响的评价 人工智能简称AI&#xff0c;最初由麦卡锡、明斯基等科学家于1956年在美国达特茅斯学院开会研讨时提出。2016年&#xff0c;人工智能AlphaGo 4:1战胜韩国围棋高手李世石&#xff0c;期后波士顿动力公司的人形机器人Atlas也展示了…

python+vue垃圾分类论坛的设计与实现85l30

环境保护是一项利国利民的重大民生工程,是造福子孙后代的幸福事,基于全面分析我国大学生环境保护教育现状的基础上提出了高校可通过开设环境类通识任选课、专业课中融入环境保护教育、环境保护实践教学、环境保护第二课堂等有效途径加强对非环境类专业大学生环境保护教育。 本系…

nest配置及环境变量

配置 配置问题&#xff1a; 直接使用.env文件&#xff0c;则会出现大量的process.env.xx的写法&#xff0c;且只能单独一个个获取&#xff0c;无法直接获取对象。 配置方案&#xff1a; 使用useClass 环境变量的配置在.env里面配置后&#xff0c;需要引入到config/envs内部…

如何有效地使用弹性伸缩,让云计算更高效

随着云计算的迅速发展&#xff0c;弹性伸缩作为一项重要的云服务功能&#xff0c;逐渐被越来越多的企业和开发者所关注。那么&#xff0c;什么是弹性伸缩&#xff0c;为什么它会成为标配云服务呢&#xff1f;下面将从三个方面来探讨这个问题。 一、首先&#xff0c;什么是弹性伸…

谈谈 Dapr 的优缺点,应用场景,以及未来的发展趋势,生态成熟度

谈谈 Dapr 的优缺点&#xff0c;应用场景&#xff0c;以及未来的发展趋势&#xff0c;生态成熟度 优点缺点应用场景未来发展趋势生态成熟度 本文采用 GPT4 生成&#xff0c;仅供参考。 Dapr 是一个分布式应用程序运行时&#xff0c;其目标是提供一组通用的功能&#xff0c;可以…

业务实战记录5:MySQL 字段别名导致的异常与思考

目录 引言案例分析关于字段别名的利弊结论 引言 在日常实战中&#xff0c;数据库查询是数据分析和决策过程中的关键环节。然而&#xff0c;由于现有字段和字段别名之间的冲突&#xff0c;我们可能会遇到意外的错误和困惑。因此&#xff0c;为了确保查询结果的准确性和可靠性&a…

华为OD机试真题 Java 实现【组合出合法最小数】【2023Q1 200分】

一、题目描述 给一个数组,数组里面都是代表非负整数的字符串,将数组里所有的数值排列组合拼接起来组成一个数字,输出拼接成的最小的数字。 二、输入描述 一个数组,数组不为空,数组里面都是代表非负整数的字符串,可以是0开头。 例如:[“13”, “045”, “09”, “56”…

Eclipse 教程Ⅱ

Eclipse 修改字符集 默认情况下 Eclipse 字符集为 GBK&#xff0c;但现在很多项目采用的是 UTF-8&#xff0c;这是我们就需要设置我们的 Eclipse 开发环境字符集为 UTF-8&#xff0c; 设置步骤如下&#xff1a; 在菜单栏选择 Window -> Preferences -> General -> W…