欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

## 404.左叶子之和 题目地址:https://leetcode-cn.com/problems/sum-of-left-leaves/ 计算给定二叉树的所有左叶子之和。 示例: ![404.左叶子之和1](https://img-blog.csdnimg.cn/20210204151927654.png) ## 思路 **首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。** 因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:**如果左节点不为空,且左节点没有左右孩子,那么这个节点就是左叶子** 大家思考一下如下图中二叉树,左叶子之和究竟是多少? ![404.左叶子之和](https://img-blog.csdnimg.cn/20210204151949672.png) **其实是0,因为这棵树根本没有左叶子!** 那么**判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。** 如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子,判断代码如下: ``` if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) { 左叶子节点处理逻辑 } ``` ## 递归法 递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。。 递归三部曲: 1. 确定递归函数的参数和返回值 判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int 使用题目中给出的函数就可以了。 2. 确定终止条件 依然是 ``` if (root == NULL) return 0; ``` 3. 确定单层递归的逻辑 当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。 代码如下: ```C++ int leftValue = sumOfLeftLeaves(root->left); // 左 int rightValue = sumOfLeftLeaves(root->right); // 右 // 中 int midValue = 0; if (root->left && !root->left->left && !root->left->right) { midValue = root->left->val; } int sum = midValue + leftValue + rightValue; return sum; ``` 整体递归代码如下: ```C++ class Solution { public: int sumOfLeftLeaves(TreeNode* root) { if (root == NULL) return 0; int leftValue = sumOfLeftLeaves(root->left); // 左 int rightValue = sumOfLeftLeaves(root->right); // 右 // 中 int midValue = 0; if (root->left && !root->left->left && !root->left->right) { // 中 midValue = root->left->val; } int sum = midValue + leftValue + rightValue; return sum; } }; ``` 以上代码精简之后如下: ```C++ class Solution { public: int sumOfLeftLeaves(TreeNode* root) { if (root == NULL) return 0; int midValue = 0; if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) { midValue = root->left->val; } return midValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right); } }; ``` ## 迭代法 本题迭代法使用前中后序都是可以的,只要把左叶子节点统计出来,就可以了,那么参考文章 [二叉树:听说递归能做的,栈也能做!](https://mp.weixin.qq.com/s/c_zCrGHIVlBjUH_hJtghCg)和[二叉树:前中后序迭代方式的写法就不能统一一下么?](https://mp.weixin.qq.com/s/WKg0Ty1_3SZkztpHubZPRg)中的写法,可以写出一个前序遍历的迭代法。 判断条件都是一样的,代码如下: ```C++ class Solution { public: int sumOfLeftLeaves(TreeNode* root) { stack st; if (root == NULL) return 0; st.push(root); int result = 0; while (!st.empty()) { TreeNode* node = st.top(); st.pop(); if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) { result += node->left->val; } if (node->right) st.push(node->right); if (node->left) st.push(node->left); } return result; } }; ``` ## 总结 这道题目要求左叶子之和,其实是比较绕的,因为不能判断本节点是不是左叶子节点。 此时就要通过节点的父节点来判断其左孩子是不是左叶子了。 **平时我们解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性。** 希望通过这道题目,可以扩展大家对二叉树的解题思路。 ## 其他语言版本 Java: **递归** ```java class Solution { public int sumOfLeftLeaves(TreeNode root) { if (root == null) return 0; int leftValue = sumOfLeftLeaves(root.left); // 左 int rightValue = sumOfLeftLeaves(root.right); // 右 int midValue = 0; if (root.left != null && root.left.left == null && root.left.right == null) { // 中 midValue = root.left.val; } int sum = midValue + leftValue + rightValue; return sum; } } ``` **迭代** ```java class Solution { public int sumOfLeftLeaves(TreeNode root) { if (root == null) return 0; Stack stack = new Stack<> (); stack.add(root); int result = 0; while (!stack.isEmpty()) { TreeNode node = stack.pop(); if (node.left != null && node.left.left == null && node.left.right == null) { result += node.left.val; } if (node.right != null) stack.add(node.right); if (node.left != null) stack.add(node.left); } return result; } } ``` Python: ```Python **递归** # Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def sumOfLeftLeaves(self, root: TreeNode) -> int: self.res=0 def areleftleaves(root): if not root:return if root.left and (not root.left.left) and (not root.left.right):self.res+=root.left.val areleftleaves(root.left) areleftleaves(root.right) areleftleaves(root) return self.res ``` Go: > 递归法 ```go /** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func sumOfLeftLeaves(root *TreeNode) int { var res int findLeft(root,&res) return res } func findLeft(root *TreeNode,res *int){ //左节点 if root.Left!=nil&&root.Left.Left==nil&&root.Left.Right==nil{ *res=*res+root.Left.Val } if root.Left!=nil{ findLeft(root.Left,res) } if root.Right!=nil{ findLeft(root.Right,res) } } ``` > 迭代法 ```go /** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func sumOfLeftLeaves(root *TreeNode) int { var res int queue:=list.New() queue.PushBack(root) for queue.Len()>0{ length:=queue.Len() for i:=0;i