1、递归算法定义
递归算法是将重复问题分解为同类的子问题而解决问题的方法,其核心思想是分治策略。
简单来说就是自己调用自己。直到达到退出递归的条件,则完成递归。
2、递归的步骤
1、找整个递归的终止条件:递归应该在什么时候结束?
2、找返回值:应该给上一级返回什么信息?
3、本级递归应该做什么:在这一级递归中,应该完成什么任务?
3、递归的优点和缺点
优点:递归的核心思想就是将一个大问题,拆解成一个小问题,然后将小问题再次拆解,层层拆分从而简化问题的实现。从而达到简化重复的代码让程序变得更加简洁。
缺点:使用递归算法时每次方法的调用都需要在栈中开辟出一个空间保存相关数据,频繁的压栈、弹栈会导致效率变低。
4、递归的案例
4.1 阶乘的算法
// 阶乘的递归实现 public static long f(int n){ if(n == 1) // 结束递归终止条件 return 1; return n*f(n-1); // 相同重复逻辑,缩小问题的规模 }
4.2 斐波纳契数列
斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……
在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)。
public static int fibonacci(int n) { if (n == 1 || n == 2) { // 递归终止条件 return 1; // 简单情景 } return fibonacci(n - 1) + fibonacci(n - 2); // 相同重复逻辑,缩小问题的规模 }
4.3 汉诺塔问题
/** * Title: 汉诺塔问题 * Description:古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。 * 有一个和尚想把这64个盘子从A座移到C座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下, * 小盘在上。在移动过程中可以利用B座。要求输入层数,运算后输出每步是如何移动的。 * */ public class HanoiTower { /** * @description 在程序中,我们把最上面的盘子称为第一个盘子,把最下面的盘子称为第N个盘子 * @author rico * @param level:盘子的个数 * @param from 盘子的初始地址 * @param inter 转移盘子时用于中转 * @param to 盘子的目的地址 */ public static void moveDish(int level, char from, char inter, char to) { if (level == 1) { // 递归终止条件 System.out.println("从" + from + " 移动盘子" + level + " 号到" + to); } else { // 递归调用:将level-1个盘子从from移到inter(不是一次性移动,每次只能移动一个盘子,其中to用于周转) moveDish(level - 1, from, to, inter); // 递归调用,缩小问题的规模 // 将第level个盘子从A座移到C座 // 递归调用:将level-1个盘子从inter移到to,from 用于周转 moveDish(level - 1, inter, from, to); // 递归调用,缩小问题的规模 public static void main(String[] args) { int nDisks = 30; moveDish(nDisks, 'A', 'B', 'C');
4.4 二叉树深度
public static int getTreeDepth(Tree t) { // 树为空 if (t == null) // 递归终止条件 return 0; int left = getTreeDepth(t.left); // 递归求左子树深度,缩小问题的规模 int right = getTreeDepth(t.left); // 递归求右子树深度,缩小问题的规模 return left > right ? left + 1 : right + 1;
// 阶乘的递归实现
public static long f(int n){
if(n == 1) // 结束递归终止条件
return 1;
return n*f(n-1); // 相同重复逻辑,缩小问题的规模
}