用std::vector回溯收集根到叶子路径的关键是在递归返回前用pop_back及时清理,确保每次进入子树前push、返回父节点前pop;传参必须为引用,路径和计算宜边递归边累加。

用 std::vector 回溯收集每条根到叶子的路径
关键不是“存路径”,而是“在递归退出时及时清理”。很多初学者直接 push_back 节点值却忘了 pop_back,导致后续路径混入前序残留。必须保证:每次进入左/右子树前 push,返回父节点前 pop。
示例核心逻辑:
void dfs(TreeNode* node, vector<int>& path, vector<vector>>& res) {
if (!node) return;
path.push_back(node->val);
if (!node->left && !node->right) {
res.push_back(path); // 叶子节点:保存当前完整路径
}
dfs(node->left, path, res);
dfs(node->right, path, res);
path.pop_back(); // 必须放在这里!回溯还原
}</vector></int>
- 不能把
path.pop_back()放在递归调用之后再判断是否为叶子——那样会漏掉叶子自身的 pop - 传参必须是引用
vector<int>& path</int>,否则每次都是拷贝,回溯失效 - 如果只关心路径和(而非路径本身),可改用 int 类型累加参数,避免 vector 拷贝开销
路径和计算:边递归边累加比事后遍历更高效
若最终只需所有路径的数字和(比如 [1,2,3] 算作 123),不要先存下所有路径再转换——容易溢出且多一次遍历。应递归中维护当前数值,每下一层执行 curr = curr * 10 + node->val。
注意整数溢出风险:
- 题目若明确节点值为 0–9 且深度 ≤ 10,
int通常够用;否则用long long - 空节点不参与计算,但需确保叶子判定条件仍为
!node->left && !node->right - 若节点值可能为负数(非常规),该十进制拼接法不适用,得改用字符串或单独求和逻辑
LeetCode 257 和 129 的典型差异点
LeetCode 257 要求返回所有路径字符串(如 ["1->2->5", "1->3"]),而 LeetCode 129 要求返回路径代表的整数之和(如 125 + 13 = 138)。二者结构相似,但数据类型和终止处理不同。
-
257中拼接用to_string+"->",叶子处 push 当前字符串,无需 pop(因为 string 是值传递或显式构造) -
129中必须用数值累加,且递归参数里带当前和,避免 vector 存储路径带来的额外内存与拷贝 - 两者都要求判空指针,但
129允许 root 为 null,此时返回 0;257同样,返回空 vector
容易被忽略的边界:空树、单节点、含 0 节点
测试时别只跑 [1,2,3]。这几个 case 一跑就暴露问题:
-
root = nullptr:函数入口要立刻返回,不能对node->val解引用 -
root = [0]:路径是[0],对应数值是 0,不是空或跳过——很多人误判 0 为无效值而跳过 -
root = [1,0,0]:产生路径[1,0]和[1,0],数值分别是 10 和 10,和为 20;若中间 0 被忽略,结果就错
真正麻烦的是路径和定义本身:题目没说清是“十进制拼接”还是“元素相加”。务必确认题干——前者是 129,后者只需在叶子处累加 accumulate(path.begin(), path.end(), 0)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











