LeetCode 分类刷题:404. 左叶子之和

题目

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

解析

我的思路

递:

从根节点开始,所有左叶子之和=左子树的左叶子之和+右子树的左叶子之和

归:

  1. 当节点为空时,返回0;

  2. 当节点不为空时:

已知当左右子树为空时,该节点是叶子节点。

问题在于如何判断是否为左叶子呢?

在遍历某个节点的子树时,需要添加一个标识:

  • 如果是左子树,标识为true;
  • 如果是右子树,标识为false。

当标识为true且左右子树为空时,返回该节点的值。

灵神思路

题意:如果一个节点的左儿子是叶子,那么把左儿子的节点值加到答案中。

在遍历二叉树的过程中,如果当前节点的左儿子是叶子,即左儿子的左右儿子均为空,那么把左儿子的节点值加到答案中。

代码直接把 sumOfLeftLeaves 当作递归函数使用。

作者:灵茶山艾府

链接:https://leetcode.cn/problems/sum-of-left-leaves/solutions/3751068/jian-dan-ti-jian-dan-zuo-pythonjavaccgoj-w8st/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

答案

我的答案:

javascript 复制代码
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
function dfs(root, isleft) {
    if(root === null) return 0;
    if(isleft && root.left === null && root.right === null) return root.val;
    return dfs(root.left, true) + dfs(root.right, false);
}
var sumOfLeftLeaves = function(root) {
    // 递:每棵树的左叶子之和等于它的左右子树中的左叶子之和
    // 归:节点为空时返回0,位于左子树且该节点的左、右子树均为空时(为叶子节点)返回该节点的值
    return dfs(root.left, true) + dfs(root.right, false);
};

灵神答案:

javascript 复制代码
var sumOfLeftLeaves = function(root) {
    if (root === null) { // 空节点
        return 0;
    }

    // 递归左右子树,收集左右子树中的「节点的左儿子是叶子」的叶子节点值之和
    let sum = sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);

    const left = root.left; // 当前节点的左儿子
    if (left && left.left === null && left.right === null) { // 当前节点的左儿子是叶子
        sum += left.val; // 累加节点值
    }

    return sum;
};

// 作者:灵茶山艾府
// 链接:https://leetcode.cn/problems/sum-of-left-leaves/solutions/3751068/jian-dan-ti-jian-dan-zuo-pythonjavaccgoj-w8st/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

**我的疑惑:**为什么在递归调用之后还要加一个判断来累加 root.left.val?

因为 在递归中,当前节点并不知道自己的左子节点是不是左叶子,除非站在父节点的视角判断。

递归逻辑分解

  1. sumOfLeftLeaves(root.left)

    进入左子树,继续寻找左叶子(在左子树的视角里,它也会判断自己的左子节点是不是左叶子)。

  2. sumOfLeftLeaves(root.right)

    进入右子树,继续寻找左叶子。

  3. 但是,root 的左子节点 root.left 如果是叶子,它在它自己的递归调用中不会被计入,因为:

    • 当递归进入 root.left 时,它看到自己左右都为 null,但它不知道自己是父亲的左孩子还是右孩子。

    • root.left 的递归中,root.left.leftroot.left.right 都是 null,所以不会进入 if 条件,只会返回 0。

    • 所以 root.left 如果是左叶子,必须由它的父节点 (root) 来识别并累加。

关键理解

  • 递归调用 sumOfLeftLeaves(root.left) 返回的是以 root.left 为根的树中所有的左叶子之和,并不包括 root.left 本身(如果它是叶子)。

  • 判断一个节点是不是左叶子,必须由它的父节点来完成,因为需要知道它是左孩子还是右孩子,以及它是不是叶子。

  • 所以代码结构是:

    1. 递归左右子树,收集它们之下的左叶子之和。

    2. 检查当前节点的直接左孩子是不是左叶子,如果是,加上它的值。

复杂度分析

时间复杂度:O(n),其中 n 是二叉树的节点个数。

空间复杂度:O(n)。最坏情况下,二叉树退化成一条链,递归需要 O(n) 的栈空间。

相关推荐
木易 士心1 小时前
th-table 中 基于双字段计算的表格列展示方案
前端·javascript·angular.js
小白程序员成长日记2 小时前
2025.11.19 力扣每日一题
算法·leetcode·职场和发展
toooooop82 小时前
uniapp多个页面监听?全局监听uni.$emit/$on
前端·javascript·uni-app
星火飞码iFlyCode3 小时前
iFlyCode+SpecKit应用:照片等比智能压缩功能实现
前端·javascript
迈巴赫车主3 小时前
蓝桥杯 20541魔法科考试
java·数据结构·算法·蓝桥杯
star learning white3 小时前
xmC语言8
c语言·开发语言·算法
GISer_Jing3 小时前
3DThreeJS渲染核心架构深度解析
javascript·3d·架构·webgl
青小俊4 小时前
【代码随想录c++刷题】-二分查找 移除元素 有序数组的平方 - 第一章 数组 part 01
c++·算法·leetcode
拉不动的猪4 小时前
文件下载:后端配置、前端方式与进度监控
前端·javascript·浏览器