leetcode算法(404.左叶子之和)

层序遍历

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;
    }
};

代码逻辑说明

  1. 使用队列进行层序遍历(BFS)

  2. 对每个节点检查其左子节点是否存在

  3. 如果存在左子节点,先将其加入队列(无论它是不是叶子节点)

  4. 然后判断这个左子节点是否是叶子节点(没有左右子节点)

  5. 如果是叶子节点,累加它的值

  6. 继续处理右子节点(将其加入队列)

二叉树递归法

递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。

递归三部曲:

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
相关推荐
Swift社区1 小时前
LeetCode 377 组合总和 Ⅳ
算法·leetcode·职场和发展
wanghu20241 小时前
ABC440_D题_题解
算法
Tisfy1 小时前
LeetCode 2975.移除栅栏得到的正方形田地的最大面积:暴力枚举所有可能宽度
算法·leetcode·题解·模拟·暴力
啊阿狸不会拉杆1 小时前
《数字图像处理》第 1 章 绪论
图像处理·人工智能·算法·计算机视觉·数字图像处理
Loo国昌1 小时前
【LangChain1.0】第二篇 快速上手实战
网络·人工智能·后端·算法·microsoft·语言模型
BHXDML1 小时前
第二章:决策树与集成算法
算法·决策树·机器学习
橘颂TA1 小时前
【剑斩OFFER】算法的暴力美学——力扣 692 题:前 K 个高频单词
网络·算法·leetcode·哈希算法·结构与算法
练习时长一年1 小时前
LeetCode热题100(乘积最大子序列)
数据结构·算法·leetcode
仰泳的熊猫1 小时前
题目1109:Hanoi双塔问题
数据结构·c++·算法·蓝桥杯