代码随想录24 leetcode404.左叶子之和

目录

404.左叶子之和

513.找树左下角的值

回溯逻辑分析

112.路径总和


404.左叶子之和

计算给定二叉树的所有左叶子之和。

示例:

给定二叉树的根节点 root ,返回所有左叶子之和。

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        if (root->left == NULL && root->right== NULL) return 0;

        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 sumOfLeftSubtrees(TreeNode* root) {
        if (root == NULL) return 0;

        int leftSum = 0;
        if (root->left != NULL) { // 如果有左子树,则加入左子树根节点的值
            leftSum += root->left->val + sumOfLeftSubtrees(root->left); // 加上左子树的和
        }
        int rightSum = sumOfLeftSubtrees(root->right); // 遍历右子树
        return leftSum + rightSum;
    }
};

513.找树左下角的值

给定一个二叉树,在树的最后一行找到最左边的值。

示例 1:

这个需要回溯。

回溯逻辑分析

  1. 深度参数传递

    • 在进入 traversal(root->left, depth)traversal(root->right, depth) 时,先增加 depth++,表示进入更深的一层。
    • 在递归调用完成后,通过 depth-- 将深度恢复到调用前的状态。
    • 回溯的本质:通过递归函数返回时,深度回到之前的值,这样确保每个分支的递归是独立的,互不干扰。
  2. 叶子节点处理

    • 当到达叶子节点时,判断当前深度是否大于已记录的最大深度(maxDepth),如果是,则更新 resultmaxDepth
    • 叶子节点处理完成后递归返回,此时调用栈回到父节点,深度恢复到进入当前节点前的状态。
cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
  int maxDepth=-1;
    int result=1;

    int findBottomLeftValue(TreeNode* root) {
         traversal(root,0);
        return result;
    }
    void traversal(TreeNode* root,int depth){
        if (root == nullptr) return; // 空节点直接返回

        if(root->left==nullptr&&root->right==nullptr){
        if(depth>maxDepth){
            maxDepth=depth;
            result = root->val;
        }
        }
        if(root->left){
            depth++;
            traversal(root->left,depth);
            depth--;
        }
         if(root->right){
            depth++;
            traversal(root->right,depth);
            depth--;
        }
    }
};

也可以不用这么每次要depth++,depth--太麻烦了,直接传递 depth+1

原因:直接使用 depth + 1 是因为在递归函数中,参数是值传递的。换句话说,传递给函数的 depth 是一个拷贝,而不是对原始变量的引用。因此,在递归过程中修改 depth 对当前函数外的调用不会有任何影响,这就避免了手动恢复 depth 的复杂性。

优化后的代码:

cpp 复制代码
void traversal(TreeNode* root, int depth) {
    if (root == nullptr) return;

    if (root->left == nullptr && root->right == nullptr) {
        if (depth > maxDepth) {
            maxDepth = depth;
            result = root->val;
        }
    }

    traversal(root->left, depth + 1);  // 左子树
    traversal(root->right, depth + 1); // 右子树
}

112.路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

叶子节点 是指没有子节点的节点。

同样的下面一道题也是利用递归的思路:

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
    
        return checkPathSum(root, 0, targetSum); // 从根节点开始递归
    }

private:
    bool checkPathSum(TreeNode* root, int currentSum, int targetSum) {
        if (root == nullptr) return false; // 遇到空节点返回 false

        // 累加当前节点的值
        currentSum += root->val;

        // 如果是叶子节点,检查路径和是否等于目标值
        if (root->left == nullptr && root->right == nullptr) {
            return currentSum == targetSum;
        }

        // 递归检查左右子树
        return checkPathSum(root->left, currentSum, targetSum) ||
               checkPathSum(root->right, currentSum, targetSum);
    }
};
相关推荐
深图智能3 分钟前
OpenCV实现Kuwahara滤波
opencv·算法·计算机视觉
东北赵四10 分钟前
JVM之垃圾回收器ZGC概述以及垃圾回收器总结的详细解析
java·jvm·算法
测试老哥14 分钟前
白盒测试用例的设计详解
自动化测试·软件测试·测试工具·职场和发展·单元测试·测试用例·测试覆盖率
hqxnb66630 分钟前
构建高效的进程池:深入解析C++实现
开发语言·c++·算法
阿七想学习37 分钟前
数据结构《Map&Set&哈希表》
java·数据结构·算法
xiaoshiguang342 分钟前
LeetCode:131. 分割回文串
java·算法·leetcode
fks1431 小时前
leetcode 115. 不同的子序列
leetcode
苏苏大大1 小时前
【leetcode19】三数之和==有点难还没看懂❗==
java·数据结构·算法·leetcode·职场和发展
啵啵鱼爱吃小猫咪1 小时前
Franka例程学习——joint_point_to_point_motion
c++·人工智能·python·算法·ubuntu·机器人
机智可爱嚎嚎2 小时前
学习python类的总结
python·学习·算法