

层序遍历
cpp
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
// 创建一个队列用于BFS(广度优先搜索)
queue<TreeNode*> que;
// 如果根节点为空,直接返回0
if(root == NULL) return 0;
// 将根节点加入队列
que.push(root);
// 用于累加左叶子节点的和
int sum = 0;
// BFS主循环:当队列不为空时继续处理
while(!que.empty()){
// 获取当前层的节点数量
int size = que.size();
// 遍历当前层的所有节点
for(int i = 0; i < size; i++){
// 取出队列前面的节点
TreeNode *node = que.front();
que.pop();
// 如果当前节点有左子节点
if(node->left){
// 将左子节点加入队列(用于后续遍历)
que.push(node->left);
// 检查左子节点是否是叶子节点
// 叶子节点:既没有左子节点也没有右子节点
if(node->left->left == NULL && node->left->right == NULL){
// 如果是左叶子节点,累加其值到sum
sum += node->left->val;
}
}
// 如果当前节点有右子节点,将其加入队列
if(node->right) que.push(node->right);
}
}
// 返回所有左叶子节点的和
return sum;
}
};
代码逻辑说明:
-
使用队列进行层序遍历(BFS)
-
对每个节点检查其左子节点是否存在
-
如果存在左子节点,先将其加入队列(无论它是不是叶子节点)
-
然后判断这个左子节点是否是叶子节点(没有左右子节点)
-
如果是叶子节点,累加它的值
-
继续处理右子节点(将其加入队列)
二叉树递归法
递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。
递归三部曲:
1.确定递归函数的参数和返回值
判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int
使用题目中给出的函数就可以了。
2.确定终止条件
如果遍历到空节点,那么左叶子值一定是0
cpp
if (root == NULL) return 0;
注意,只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。
所以如果当前遍历的节点是叶子节点,那其左叶子也必定是0,那么终止条件为:
cpp
if (root->left == NULL && root->right== NULL) return 0;
//其实这个也可以不写,如果不写不影响结果,但就会让递归多进行了一层。
3.确定单层递归的逻辑
当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。
cpp
int leftValue = sumOfLeftLeaves(root->left); // 左
if (root->left && !root->left->left && !root->left->right) {
leftValue = root->left->val;
}
int rightValue = sumOfLeftLeaves(root->right); // 右
int sum = leftValue + rightValue; // 中
return sum;
整体递归代码如下:
cpp
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
// 1. 基本情况1: 如果当前节点为空,返回0
if (root == NULL) return 0;
// 2. 基本情况2: 如果当前节点是叶子节点(没有左右子节点)
// 注意:这里叶子节点返回0,因为叶子节点本身不是左叶子
// 只有作为左子节点的叶子才需要计算
if (root->left == NULL && root->right == NULL) return 0;
// 3. 递归计算左子树中的所有左叶子节点之和
// 注意:这个递归调用可能会返回0,即使左子节点是叶子节点
// 因为上面的基本情况2会让叶子节点返回0
int leftValue = sumOfLeftLeaves(root->left); // 左
// 4. 关键判断:如果当前节点的左子节点存在,并且是叶子节点
// !root->left->left:左子节点没有左子节点
// !root->left->right:左子节点没有右子节点
// 满足这两个条件说明左子节点是叶子节点
if (root->left && !root->left->left && !root->left->right) {
// 5. 覆盖之前递归计算的结果
// 因为递归调用sumOfLeftLeaves(root->left)会返回0
// (左叶子节点本身会返回0,根据基本情况2)
// 但实际上我们需要计算这个左叶子节点的值
leftValue = root->left->val;
}
// 6. 递归计算右子树中的所有左叶子节点之和
int rightValue = sumOfLeftLeaves(root->right); // 右
// 7. 将左右子树的结果相加,得到当前子树的总和
int sum = leftValue + rightValue; // 中
// 8. 返回当前子树的所有左叶子节点值之和
return sum;
}
};
举例:
3
/ \
9 20
/ \
15 7
步骤1:节点3开始执行
sumOfLeftLeaves(3):
root=3
1. if(root==NULL)不符合
2. if(3.left==NULL && 3.right==NULL) 不符合 (9和20都不为空)
3. leftValue = sumOfLeftLeaves(9) // 入栈
步骤2:节点9开始执行
sumOfLeftLeaves(9):
root=9
1. if(root==NULL) → 不符合
2. if(9.left==NULL && 9.right==NULL) → 符合 ,所以return 0
执行: return 0 // 出栈
然后节点9返回0,回到节点3
步骤3:节点3继续执行(左子树返回后)
sumOfLeftLeaves(3)继续:
leftValue = 0 // 从sumOfLeftLeaves(9)得到
// 关键判断
if(3.left && !3.left->left && !3.left->right):
3.left=9, 9.left=NULL, 9.right=NULL → 条件成立
leftValue = 9 // 所以leftValue覆盖为9.val,现在leftValue为9
rightValue = sumOfLeftLeaves(20) // 入栈
......
......
......
sumOfLeftLeaves(3)
├── leftValue = sumOfLeftLeaves(9) → 0 → 修正为9
└── rightValue = sumOfLeftLeaves(20)
├── leftValue = sumOfLeftLeaves(15) → 0 → 修正为15
└── rightValue = sumOfLeftLeaves(7) → 0
└── sum = 15 + 0 = 15
└── sum = 9 + 15 = 24