递归核心思维:宏观视角
很多人初次接触递归时,容易陷入对函数调用细节的纠结,甚至产生畏难情绪。其实理解递归的关键在于建立宏观视角:相信函数的功能。就像我们调用一个加法函数是为了利用它的结果,而不是去关心它内部如何计算一样。
以归并排序为例,mergesort 的功能是将无序数组变为有序。当我们调用 mergesort(left) 和 mergesort(right) 时,无需深究它们内部如何展开,只需相信调用后左右两部分已有序,剩下的工作就是合并。这种'信任'是编写递归代码的心理基础,配合明确的终止条件(如 n=1),即可构建稳定的递归逻辑。
1. 汉诺塔问题
题目描述
有三根柱子 A、B、C,A 柱上有 n 个大小不同的圆盘,从小到大叠放。要求将 A 柱上的所有盘子移动到 C 柱,移动过程中大盘子不能压在小盘子上面,且每次只能移动一个盘子。
算法思路
这是一个经典的递归场景。我们可以将规模为 n 的问题拆解为三个步骤:
- 将 A 柱上方的 n-1 个盘子借助 C 柱移动到 B 柱;
- 将 A 柱最底下的第 n 个盘子直接移动到 C 柱;
- 将 B 柱上的 n-1 个盘子借助 A 柱移动到 C 柱。
当 n=1 时,直接移动即可,这是递归的终止条件。通过这种分治策略,无论盘子数量多少,都能找到通用的移动路径。
C++ 实现
class Solution {
public:
void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
dfs(A, B, C, A.size());
}
private:
void dfs(vector<int>& x, vector<int>& y, vector<int>& z, int n) {
// 递归结束条件:只剩一个盘子,直接从 x 移到 z
if (n == 1) {
z.push_back(x.back());
x.pop_back();
return;
}
// 1. 将 x 上的 n-1 个盘子借助 z 移到 y
dfs(x, z, y, n - 1);
z.(x.());
x.();
(y, x, z, n - );
}
};




