如何求二叉树所有左叶子之和

117 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第33天,点击查看活动详情 >>

如何求二叉树所有左叶子之和

问题设定

对于给定的二叉树,用算法计算返回该二叉树所有左叶子结点的数值之和。

比如:

二叉树:root = [3,9,20,null,null,15,7]

所有左叶子结点数值之和为 24

问题分析

这个问题相信大家一下子就明白它的意思了,如何是让大家笔算的话,相信各位可以很快第就计算出来了,毕竟这题的思路都很清晰(找到所有左叶子结点,在将它们的数值全部相加,求和);但是这个过程如何要用算法展示出来的话,可能就有点复杂了。

主要有以下几个问题:

  1. 如何判断当前结点是不是左叶子结点
  2. 如何对所有左叶子结点进行数值求和

设计算法

在这里,本文主要介绍的是一种递归的方法,这种方法是比较容易理解的。

下面我们就一起来看看这个算法到底是如何设计的吧。

递归终止条件:

if (root == null) {
    return 0;
}

递归计算左右子树中所有左节点的数值之和:

int leftNodeValue = sumOfLeftLeaves(root.left);    // 左
int rightNodeValue = sumOfLeftLeaves(root.right);  // 右

对于左叶子节点的处理:

int midValue = 0;
if (root.left != null && root.left.left == null && root.left.right == null) { // 中
    midValue = root.left.val;
}

经过了以上的分析,相信各位可以很容易就实现了整个算法了:

具体代码实现,如下所示:

public int sumOfLeftLeaves(TreeNode root) {
    // 递归终止条件
    if (root == null) {
        return 0;
    }
    /**
     * leftNodeValue 在底层的时候是一个左节点
     * 但是随着递归的不断回溯,leftNodeValue 记录的就是从当前层左子树往下的所有左节点之和
     */
    int leftNodeValue = sumOfLeftLeaves(root.left);    // 左
    int rightNodeValue = sumOfLeftLeaves(root.right);  // 右
    // 中
    int midValue = 0;
    if (root.left != null && root.left.left == null && root.left.right == null) { // 中
        midValue = root.left.val;
    }
    return midValue + leftNodeValue + rightNodeValue;
 }

总结:

下面我们对整个算法进行总结,对于一些需要特别注意的细节进行再次说明。

在最后返回的时候, return midValue + leftNodeValue + rightNodeValue;,它的主要含义是:

正常返回,递归究竟计算什么是由它来主导的 它返回的是什么,那么整个递归计算的就是什么 如果当前根节点的左边是左节点,则 midValue 记录该值 如果当前根节点的左边是左子树,则 leftNodeValue 记录的是左子树中所有左节点之和 如果当前根节点的右边是右子树,则 rightNodeValue 记录的是右子树中所有左节点之和

对于整个递归算法的技巧总结:

函数递归并不是一定是求什么的, 函数递归它本身只是一种路线,这里就是对树的一种遍历, 具体这过程中,要求什么,计算什么,并不是由它来决定了, 而是由单层递归中,所有 return 组合来反映的。

比如说: 这里递归返回计算的就是左节点之和,递归终止条件还是空节点; 但是,另外一个 return 它计算的是以当前 root 为根节点的树的左节点之和, 其实递归计算当中,一般只要底层逻辑处理好就行了,上面是不断递归的,一般不会有问题。

比如说,这里是要求二叉树的左节点之和,本质上只有三种情况: 1、根左右(三个节点) 2、根左 3、根右

其实在二叉树中,递归的时候,最主要是这样考虑: 1、题目要求 求的是什么 2、子节点的情况怎么处理 3、子树的情况又怎么处理