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) 的栈空间。

相关推荐
想唱rap27 分钟前
应用层协议与序列化
linux·运维·服务器·网络·数据结构·c++·算法
拉里呱唧27 分钟前
一个像在使用PPT的在线 HTML 编辑器:HeyHTML
javascript·交互·html5
重生之我是Java开发战士33 分钟前
【笔试强训】Week3:重排字符串,分组,DNA序列
算法
We་ct34 分钟前
LeetCode 97. 交错字符串:动态规划详解
前端·算法·leetcode·typescript·动态规划
热心网友俣先生38 分钟前
2026年第二十三届五一数学建模竞赛B题四问参考答案+多算法对比
算法·数学建模
无敌昊哥战神39 分钟前
【LeetCode 37】解数独 (Sudoku Solver) —— 回溯法详解 (Python/C/C++)
c语言·c++·python·算法·leetcode
风筝在晴天搁浅1 小时前
LeetCode 162.寻找峰值
算法·leetcode
itzixiao1 小时前
L1-067 洛希极限(10分)[java][python]
java·开发语言·算法
jinyishu_1 小时前
链表经典OJ题
c语言·数据结构·算法·链表
葫三生1 小时前
三生原理文章被AtomGit‌开源社区收录的意义探析?
人工智能·深度学习·神经网络·算法·搜索引擎·开源·transformer