下面代码执行后的输出是( )。
#include <iostream>
using namespace std;
int jumpFloor(int N) {
cout << N << "#";
if (N == 1 || N == 2) {
return N;
} else {
return jumpFloor(N - 1) + jumpFloor(N - 2);
}
}
int main() {
cout << jumpFloor(4) << endl;
return 0;
}这题表面是斐波那契递归,实则考递归执行顺序与输出时机。拿到题先看 cout 在函数开头还是结尾,再顺着调用栈一层层推,别被返回值数字带偏,记住每次函数进栈先输出一串,出栈才加总。
最易错在忽略 cout 的侧输出时机,以为只输出最终返回值,或者把递归树里同一层的输出顺序搞反。比如 jumpFloor(3) 会先调 jumpFloor(2) 再调 jumpFloor(1),所以 2# 必在 1# 前面,选项 B 把 2# 放后面就是典型错误;还有人会只算出末尾的 5,却漏掉前面所有的#,或者把中间某次返回的 2 误当成最终结果。
【考点】递归执行流程|函数调用栈|输出时机
这道题考查的是递归函数中 cout 语句的执行顺序,以及递归树中各节点被访问的时间线。很多同学看到 jumpFloor(4) 最终返回 5,就以为输出里只有一个 5,或者只盯着返回值数字做加法,完全忽略了 cout 在函数开头就执行了。命题人就是想挖这个坑:你不仅要会算斐波那契数列,还得懂递归是怎么一层层展开的。
【解题心法】拿到这种带输出的递归题,先看 cout 写在 return 前还是后。这题 cout 在函数最前面,意味着每进入一次函数,立刻输出一串字符,然后再去递归调用。所以输出的顺序就是函数被调用的顺序,而不是返回值的顺序。
【逐层推演】 1. main 调用 jumpFloor(4),函数头先 cout << 4 << "#",输出 4#。此时进入 else 分支,要算 jumpFloor(3) + jumpFloor(2)。 2. 先执行 jumpFloor(3):函数头 cout 3#,输出 3#。再进入 else,要算 jumpFloor(2) + jumpFloor(1)。 3. 先执行 jumpFloor(2):函数头 cout 2#,输出 2#。满足 if 条件,直接 return 2,不再递归。 4. 回到 jumpFloor(3) 的 else 分支,现在要执行 jumpFloor(1):函数头 cout 1#,输出 1#。满足 if 条件,直接 return 1。 5. jumpFloor(3) 的 else 分支结束,返回 2 + 1 = 3。 6. 回到 jumpFloor(4) 的 else 分支,现在要执行 jumpFloor(2):函数头 cout 2#,输出 2#。满足 if 条件,直接 return 2。 7. jumpFloor(4) 的 else 分支结束,返回 3 + 2 = 5。 8. main 函数接着 cout << 5 << endl,输出 5。
把上面所有 cout 的输出连起来就是:4#3#2#1#2#5,对应选项 D。
【避坑指南】
【考频与趋势】 从题库统计看,"函数与递归"考点在 GESP 五级考了 19 题,属于高频重点。近年趋势明显:2023 年考了 13 题,2024 年 18 题,2025 年 21 题,2026 年 6 题,说明命题人越来越喜欢把递归和输出顺序、副作用结合起来考,纯算返回值的题目在减少。位运算虽然也考得多(2026 年 98 题),但和递归结合的题目相对少,未来可能会在递归题里穿插一些简单的位运算陷阱,比如用位运算做斐波那契的优化,或者在输出里埋一些异或的坑。
【预测】 基于现有数据,未来 GESP 五级继续考递归时,大概率还会用"输出顺序"或"返回值与副作用混合"的方式挖坑,比如把 cout 放到 return 之后,或者在递归里加一个全局变量累加输出。如果数据不足以支撑更具体的预测,那我们就说"暂无足够依据预测",但就这道题而言,趋势已经很清晰:别只背公式,要会看调用栈。