在算法设计中,** 递归(Recursion)和递推(Recurrence)** 是两种处理问题的核心思路,常用于解决具有重复子问题或递推关系的场景。它们的核心区别在于:
问题:计算 \( n! = n \times (n-1) \times \dots \times 1 \)递归思路:\( n! = n \times (n-1)! \),基例为 \( 0! = 1 \)。
#include
using namespace std;
// 递归实现阶乘
int factorial(int n) {
if (n == 0) return 1; // 终止条件
return n * factorial(n-1); // 递归调用
}
int main() {
cout << "5! = " << factorial(5) << endl; // 输出120
return 0;
}
优点 |
缺点 |
代码简洁,符合数学定义 |
多次重复计算,效率低下(如斐波那契) |
适合树状 / 分治结构问题 |
可能导致栈溢出(递归深度过大) |
问题:计算第 n 项斐波那契数 \( f(n) = f(n-1) + f(n-2) \)递推思路:从 f (0) 和 f (1) 开始,逐项计算到 f (n)(避免递归的重复计算)。
#include
using namespace std;
// 递推实现斐波那契
int fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int a = 0, b = 1, c;
for (int i=2; i<=n; i++) {
c = a + b; // 递推公式
a = b; // 状态更新
b = c;
}
return b;
}
int main() {
cout << "f(10) = " << fibonacci(10) << endl; // 输出55
return 0;
}
特征 |
递归 |
递推 |
思维方向 |
自顶向下(分解问题) |
自底向上(逐步构建) |
实现方式 |
函数调用自身 |
循环 + 迭代变量 |
空间复杂度 |
可能有较高栈空间消耗(递归深度) |
通常较低(可优化为常数空间) |
效率 |
可能重复计算(如朴素斐波那契) |
无重复计算,效率更高 |
适用场景 |
树结构、分治问题、逻辑简洁场景 |
大规模数据、需要优化效率的场景 |
在递归过程中存储子问题的解,避免重复计算,本质是递归 + 缓存(自顶向下的 DP)。
#include
#include
using namespace std;
vector
int fib_memo(int n) {
if (memo[n] != -1) return memo[n]; // 直接取缓存
if (n <= 1) return memo[n] = n;
return memo[n] = fib_memo(n-1) + fib_memo(n-2); // 计算并缓存
}
int main() {
cout << "f(50) = " << fib_memo(50) << endl; // 快速计算大数
return 0;
}
将递归的调用栈手动转化为循环结构,避免栈溢出,同时保持高效。步骤:
有 A、B、C 三根柱子,A 柱上有 n 个大小不同的盘子(下大上小),每次只能移动一个盘子,且任何时候大盘子不能放在小盘子上。求将所有盘子从 A 移到 C 的步骤。
void hanoi(int n, char from, char to, char aux) {
if (n == 1) {
cout << "Move disk 1 from " << from << " to " << to << endl; // 基例
return;
}
hanoi(n-1, from, aux, to); // 将n-1个盘子从from移到aux(借助to)
cout << "Move disk " << n << " from " << from << " to " << to << endl; // 移动最大盘子
hanoi(n-1, aux, to, from); // 将n-1个盘子从aux移到to(借助from)
}
int main() {
hanoi(3, 'A', 'C', 'B'); // 输出7步移动过程
return 0;
}
汉诺塔的递推实现需用栈模拟递归过程,记录每个状态的参数(n, from, to, aux),适合理解递归的底层机制,但代码较复杂。
递归和递推是解决具有层次结构或递推关系问题的两把利器:
都看会了吧,不会可以再评论区问,给个赞再走吧