LeetCode 404:左叶子之和(Sum of Left Leaves)
文章目录
- 摘要
- 描述
- 题解答案
- 题解代码分析
- 思路讲解:
- 示例测试及结果
- 时间复杂度
- 空间复杂度
- 总结
摘要
在日常开发中,树形结构是我们经常会碰到的一类数据,比如菜单结构、组织架构、文件系统、或者语法树。而在这些结构中,我们有时需要针对某些特定的节点做聚合计算,比如“求所有左叶子的值之和”。
这道题其实就是一个非常典型的树遍历与判断逻辑结合的题目。看似简单,但它考察了如何准确识别左叶子、如何递归遍历树以及如何在遍历中累加计算结果。本文我们就用 Swift 来带你一步步分析并实现这个题目。
描述
题目要求很清晰:
给定一棵二叉树的根节点 root
,返回所有左叶子节点的值之和。
左叶子指的是“父节点的左子节点”,并且这个左子节点本身没有子节点(也就是它是叶子)。
举个例子
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 左叶子是 9 和 15,它们的和是 24。
题解答案
解决这个问题其实很自然地想到递归。
我们可以从根节点出发,去看它的左右子节点:
- 如果左子节点存在,并且它是一个叶子,那么直接加上它的值。
- 如果不是叶子,就递归地去继续找。
- 右子节点同理,只不过我们不去累加它(因为右叶子不计入结果)。
题解代码分析
下面是完整的 Swift 代码实现,可直接在 Xcode 或 LeetCode Playground 中运行:
import Foundation// 定义树节点结构
public class TreeNode {public var val: Intpublic var left: TreeNode?public var right: TreeNode?public init() { self.val = 0; self.left = nil; self.right = nil }public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil }public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {self.val = valself.left = leftself.right = right}
}class Solution {func sumOfLeftLeaves(_ root: TreeNode?) -> Int {guard let node = root else { return 0 }var sum = 0// 判断当前节点的左子节点是否是叶子if let left = node.left {if left.left == nil && left.right == nil {sum += left.val} else {sum += sumOfLeftLeaves(left)}}// 右子树递归(但不直接加右叶子)if let right = node.right {sum += sumOfLeftLeaves(right)}return sum}
}
思路讲解:
-
递归出口:如果当前节点为空,直接返回 0。
-
左子树判断:
- 如果当前节点的左子树存在且是叶子(没有左右子节点),累加它的值。
- 如果不是叶子,就递归地继续往下找左叶子。
-
右子树判断:
- 递归计算右子树中的左叶子之和(注意不是右叶子!)。
-
返回结果:不断回传计算结果,最终得到整个树的左叶子之和。
示例测试及结果
下面我们构建一个简单的示例二叉树,并测试一下上面的代码是否正确:
// 构造示例树
// 3
// / \
// 9 20
// / \
// 15 7
let root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20, TreeNode(15), TreeNode(7))let solution = Solution()
let result = solution.sumOfLeftLeaves(root)
print("左叶子之和为:\(result)")
输出结果:
左叶子之和为:24
一切正常,和题目示例一致
再测试一个边界情况:
let single = TreeNode(1)
print("单节点树左叶子之和:\(solution.sumOfLeftLeaves(single))")
输出:
单节点树左叶子之和:0
因为它没有左叶子,结果自然为 0。
时间复杂度
每个节点只会被访问一次,递归操作也都是常数时间判断。
因此时间复杂度是:
O(n) —— 其中 n 是二叉树的节点总数。
空间复杂度
在递归过程中,系统栈的最大深度取决于树的高度。
最坏情况下(树退化为链表)为 O(n),平均情况约为 O(log n)。
因此:
空间复杂度:O(h),其中 h 是树的高度。
总结
这道题的核心不在于算法复杂度,而在于如何准确识别“左叶子”。
我们要注意两个关键点:
- 必须是左节点(不是右节点)
- 必须是叶子节点(没有左右子节点)
整体思路非常自然,用递归最简洁,但如果在性能敏感的场景下,也可以用 BFS 或栈模拟递归实现迭代版。
在实际开发中,类似的“聚合型遍历问题”非常常见,比如:
- 统计树中所有叶子节点的数量
- 累加某种类型节点的值
- 查找满足特定条件的节点路径
掌握这类递归模式,几乎可以解决 80% 的树结构算法题。