左叶子节点是指既是父节点的左子节点又无左右子节点的节点;仅靠存在left指针判断会导致非叶左子节点被误计,故递归需传布尔参数标识方向,迭代则需栈中存储节点及方向信息。

什么是左叶子节点,为什么不能只靠 left 判断
左叶子节点不是“有 left 指针的节点”,而是:它自身是某个父节点的左子节点,且它自己没有左右子节点(即 left == nullptr && right == nullptr)。常见错误是只检查 node->left 是否存在,就把它当左叶子加进去——这会把所有左子非叶节点也计入,比如根节点的左孩子若还有子树,它就不是叶子。
递归实现时必须传入“方向”标识
单纯递归遍历无法区分当前节点是父节点的左子还是右子,所以得额外参数标记。推荐用布尔值:true 表示当前节点是左子,false 表示右子。根节点没有父节点,不参与计数,所以从 root 开始递归时,左右子调用分别传 true 和 false。
关键逻辑:
- 空节点直接返回 0
- 若当前节点是叶子(
left == nullptr && right == nullptr)且is_left == true,返回它的val - 否则递归左右子:左子传
true,右子传false
示例片段:
int sumOfLeftLeaves(TreeNode* root) {
if (!root) return 0;
return dfs(root->left, true) + dfs(root->right, false);
}
int dfs(TreeNode* node, bool is_left) {
if (!node) return 0;
if (!node->left && !node->right)
return is_left ? node->val : 0;
return dfs(node->left, true) + dfs(node->right, false);
}
迭代写法容易漏掉“方向”信息,需用栈配对存储
用 stack<pair bool>></pair>,每个元素存节点指针和它是否为左子。入栈时明确标注:左子压入 {node->left, true},右子压入 {node->right, false}。出栈后只在满足“叶子 + 左子”时累加。
常见坑:
- 只用
stack<treenode></treenode>,丢掉了方向信息,无法判断是否为左叶子 - 入栈顺序或条件写反,比如把右子标成
true - 忘记判空,对
nullptr调用left/right
测试时别忽略单边树和空树边界
典型易错 case:
-
root = [1]→ 无子节点,结果为 0(根不算左叶子) -
root = [1,2,null,3]→ 节点 3 是节点 2 的左子且为叶子,结果为 3 -
root = [1,null,2]→ 节点 2 是右子,不计入,结果为 0
真正麻烦的是嵌套深、左右交错的结构,建议手画三到四层树,标清每个节点的“是否左子”和“是否叶子”,再对照代码走一遍流程。方向标识一旦错一位,整个路径上的左叶子就全乱了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











