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
相关推荐
Black蜡笔小新1 小时前
自动化AI算法训练服务器DLTM助力医学影像分析进入AI智能分析新时代
人工智能·算法·自动化
手写码匠2 小时前
深入解析大模型架构之争:全能通用模型 vs 领域专精模型
人工智能·深度学习·算法·aigc
浅念-2 小时前
LeetCode 回溯算法题——综合练习
数据结构·c++·算法·leetcode·职场和发展·深度优先·dfs
列星随旋3 小时前
线段树和树状数组的学习
学习·算法
圣保罗的大教堂3 小时前
leetcode 61. 旋转链表 中等
leetcode
全糖可乐气泡水5 小时前
Codex适配国产信创环境安装部署与技术适配全解析
开发语言·git·python·算法·百度
h_a_o777oah5 小时前
状态机+划分型 DP :深度解析K-划分问题下 DP 状态的转移逻辑(洛谷P2679 P2331 附C++代码)
c++·算法·动态规划·acm·状态机dp·划分型dp·滚动数组优化
05候补工程师5 小时前
从算法理想向工程现实的跨越:SLAM 核心架构、思维误区与 Nav2 实战避坑指南
人工智能·算法·安全·架构·机器人
手写码匠6 小时前
Android 17 适配实战指南:新特性解读、隐私变更与迁移全攻略
人工智能·深度学习·算法·aigc