给定二叉树的根节点 root ,返回所有左叶子之和。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1]
输出: 0
题目:https://leetcode.cn/problems/sum-of-left-leaves/
视频:二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和_哔哩哔哩_bilibili
首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。
因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点
思考一下如下图中二叉树,左叶子之和究竟是多少?
其实是0,因为这棵树根本没有左叶子!
但看这个图的左叶子之和是多少?
相信通过这两个图,大家对最左叶子的定义有明确理解了。
那么判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。
如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子,判断代码如下:
if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) {
左叶子节点处理逻辑
}
递归三部曲:
1、确定递归函数的参数和返回值
判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int,使用题目中给出的函数就可以了。
2、确定终止条件
如果遍历到空节点,那么左叶子值一定是0
if (root == NULL) return 0;
注意,只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。 所以如果当前遍历的节点是叶子节点,那其左叶子也必定是0,那么终止条件为:
if (root == NULL) return 0;
//其实这个也可以不写,如果不写不影响结果,但就会让递归多进行了一层。
if (root->left == NULL && root->right== NULL) return 0;
3、确定单层递归的逻辑
当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。
代码如下:
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;
迭代法使用前中后序都是可以的,只要把左叶子节点统计出来,就可以了
判断条件都是一样的
这道题目要求左叶子之和,其实是比较绕的,因为不能判断本节点是不是左叶子节点。
此时就要通过节点的父节点来判断其左孩子是不是左叶子了。
平时我们解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性。
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
// 如果根节点为空,则返回0
if (root == nullptr) return 0;
// 如果根节点没有左右子节点,则返回0
if (root->left == nullptr && root->right == nullptr) return 0;
// 递归计算左子树中左叶子节点的值的和
int leftValue = sumOfLeftLeaves(root->left);
// 如果当前节点的左子节点存在,并且左子节点没有左右子节点,
// 则将左子节点的值加入到左叶子节点的和中
if (root->left && root->left->left == nullptr && root->right->right == nullptr){
leftValue = root->left->val;
}
// 递归计算右子树中左叶子节点的值的和
int rightValue = sumOfLeftLeaves(root->right);
// 将左子树和右子树中左叶子节点的和相加得到总和
int sum = leftValue + rightValue;
// 返回总和
return sum;
}
};
这段代码的主要思路是递归计算二叉树中所有左叶子节点的值的和。具体实现方式是: 1. 如果根节点为空,则返回0。 2. 如果根节点没有左右子节点,则返回0。 3. 递归计算左子树中左叶子节点的值的和。 4. 如果当前节点的左子节点存在,并且左子节点没有左右子节点,则将左子节点的值加入到左叶子节点的和中。 5. 递归计算右子树中左叶子节点的值的和。 6. 将左子树和右子树中左叶子节点的和相加得到总和。 7. 返回总和。 需要注意的是,在第4步中,我们需要判断当前节点的左子节点是否存在,否则会导致空指针异常。同时,我们还需要判断左子节点是否没有左右子节点,才能将其加入到左叶子节点的和中。
class Solution{
public:
int sumOfLeftLeaves(TreeNode* root) {
// 如果根节点为空,返回0
if (root == nullptr) return 0;
// 定义一个栈,将根节点压入栈中
stack st;
st.push(root);
// 定义结果变量
int result = 0;
// 当栈不为空时,循环
while (!st.empty()) {
// 取出栈顶元素
TreeNode* node = st.top();
st.pop();
// 如果左子节点存在且左子节点没有子节点,将左子节点的值加入结果变量中
if (node->left && node->left->left == nullptr && node->left->right == nullptr) {
result += node->left->val;
}
// 如果右子节点存在,将右子节点压入栈中
if (node->right) st.push(node->right);
// 如果左子节点存在,将左子节点压入栈中
if (node->left) st.push(node->left);
}
// 返回结果变量
return result;
}
};
代码思路: 1. 定义一个栈,将根节点压入栈中。 2. 当栈不为空时,循环: - 取出栈顶元素。 - 如果左子节点存在且左子节点没有子节点,将左子节点的值加入结果变量中。 - 如果右子节点存在,将右子节点压入栈中。 - 如果左子节点存在,将左子节点压入栈中。 3. 返回结果变量。