递归算法基础概念
递归是一种通过函数调用自身来解决问题的方法。它通常用于解决可以分解为更小子问题的问题,如阶乘、斐波那契数列和树的遍历等。
递归三要素
-
终止条件(Base Case)
递归必须有一个明确的终止条件,否则会导致无限递归和栈溢出。 -
递归调用(Recursive Call)
问题必须能够分解为更小的同类子问题,并通过递归调用解决。 -
逐步逼近终止条件
每次递归调用都应使问题规模减小,最终达到终止条件。
递归示例:计算阶乘
阶乘是经典的递归问题,定义为 n! = n × (n-1)!,且 0! = 1。
java复制插入
public class Factorial {
public static int factorial(int n) {
if (n == 0) { // 终止条件
return 1;
}
return n * factorial(n - 1); // 递归调用
}
public static void main(String[] args) {
System.out.println(factorial(5)); // 输出 120
}
}
复制插入
递归示例:斐波那契数列
斐波那契数列定义为 F(n) = F(n-1) + F(n-2),且 F(0) = 0,F(1) = 1。
java复制插入
public class Fibonacci {
public static int fibonacci(int n) {
if (n == 0) { // 终止条件
return 0;
}
if (n == 1) { // 终止条件
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2); // 递归调用
}
public static void main(String[] args) {
System.out.println(fibonacci(6)); // 输出 8
}
}
复制插入
递归与尾递归优化
普通递归可能因栈深度过大导致栈溢出。尾递归是一种优化形式,递归调用是函数的最后一步操作。
java复制插入
public class TailRecursion {
public static int factorialTail(int n, int accumulator) {
if (n == 0) {
return accumulator;
}
return factorialTail(n - 1, n * accumulator); // 尾递归调用
}
public static void main(String[] args) {
System.out.println(factorialTail(5, 1)); // 输出 120
}
}
复制插入
递归的优缺点
优点
- 代码简洁,易于理解。
- 适合解决分治问题(如树、图遍历)。
缺点
- 可能引发栈溢出。
- 重复计算(如斐波那契数列的普通递归)。
- 性能通常低于迭代实现。
递归的替代方案
对于性能敏感的场景,可以用迭代或动态规划替代递归。例如斐波那契数列的迭代实现:
java复制插入
public class FibonacciIterative {
public static int fibonacci(int n) {
if (n <= 1) {
return n;
}
int a = 0, b = 1;
for (int i = 2; i <= n; i++) {
int temp = a + b;
a = b;
b = temp;
}
return b;
}
public static void main(String[] args) {
System.out.println(fibonacci(6)); // 输出 8
}
}
复制插入
递归的应用场景
-
数学问题
如阶乘、斐波那契数列、汉诺塔等。 -
数据结构遍历
如二叉树的前序、中序、后序遍历。 -
分治算法
如归并排序、快速排序。 -
回溯算法
如八皇后问题、迷宫求解。
递归是算法设计中的重要工具,但需谨慎使用以避免性能问题。
926

被折叠的 条评论
为什么被折叠?



