携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第33天,点击查看活动详情 >>
如何求二叉树所有左叶子之和
问题设定
对于给定的二叉树,用算法计算返回该二叉树所有左叶子结点的数值之和。
比如:
二叉树:root = [3,9,20,null,null,15,7]
所有左叶子结点数值之和为 24
问题分析
这个问题相信大家一下子就明白它的意思了,如何是让大家笔算的话,相信各位可以很快第就计算出来了,毕竟这题的思路都很清晰(找到所有左叶子结点,在将它们的数值全部相加,求和);但是这个过程如何要用算法展示出来的话,可能就有点复杂了。
主要有以下几个问题:
- 如何判断当前结点是不是左叶子结点
- 如何对所有左叶子结点进行数值求和
设计算法
在这里,本文主要介绍的是一种递归的方法,这种方法是比较容易理解的。
下面我们就一起来看看这个算法到底是如何设计的吧。
递归终止条件:
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、子树的情况又怎么处理