二叉树左叶子之和

1题目

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

二叉树左叶子之和_第1张图片

示例 1:

输入: root = [3,9,20,null,null,15,7] 
输出: 24 
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:

输入: root = [1]
输出: 0

2链接

题目:https://leetcode.cn/problems/sum-of-left-leaves/

视频:二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和_哔哩哔哩_bilibili

3解题思路

3.1递归法

首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。

因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点

思考一下如下图中二叉树,左叶子之和究竟是多少?

二叉树左叶子之和_第2张图片

 其实是0,因为这棵树根本没有左叶子!

但看这个图的左叶子之和是多少?

二叉树左叶子之和_第3张图片

相信通过这两个图,大家对最左叶子的定义有明确理解了。

那么判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。

如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子,判断代码如下:

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;

3.2 迭代法

迭代法使用前中后序都是可以的,只要把左叶子节点统计出来,就可以了

判断条件都是一样的

这道题目要求左叶子之和,其实是比较绕的,因为不能判断本节点是不是左叶子节点。

此时就要通过节点的父节点来判断其左孩子是不是左叶子了。

平时我们解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性。

4代码

4.1递归法

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步中,我们需要判断当前节点的左子节点是否存在,否则会导致空指针异常。同时,我们还需要判断左子节点是否没有左右子节点,才能将其加入到左叶子节点的和中。

 4.2迭代法

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. 返回结果变量。

 

你可能感兴趣的:(LeetCode练习,算法,leetcode)