0
点赞
收藏
分享

微信扫一扫

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)


一、题目

给你一棵二叉树的根节点 root ,请你返回 层数最深的叶子节点的和

二、示例

2.1> 示例1

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)_深度优先

【输入】root = [1,2,3,4,5,null,6,7,null,null,null,null,8]
【输出】15

2.2> 示例 2:

【输入】root = [6,7,8,2,7,1,3,9,null,1,4,null,null,null,5]
【输出】19

提示:

  • 树中节点数目在范围 [1, 104] 之间。
  • 1 <= Node.val <= 100

三、解题思路

3.1> 思路1:广度优先算法

根据题目描述,需要获得层数最深的节点的和,那么既然涉及的是某一层,所以我们会首先想到采用广度优先算法来统计某一层中节点的总和。

既然确定了要采用广度优先算法来解题,那么我们首先需要一个队列,来存储每层的节点。也就是说,首先我们将root节点放入到队列中,然后开启while的循环,那么只有当队列中是空的情况下,才会结束while循环。那么在while循环中,我们首先将root节点“踢出”队列,然后判断,如果有左子节点,则将左子节点放入到队列中;如果有右子节点,那么同样,也将其放入到队列中;对于没有左子节点或者右子节点的情况,我们不予理会就可以了。

那么此时有的同学就会有疑问,如果队列中有多个节点呢,你虽然踢出了一个节点,但是将其左右子节点又放入了队列中,那么此时岂不是就包含了两种节点了:

  • 种类一:与被踢出的节点是同一层的节点。
  • 种类二:被踢出的节点的子节点。

那队列中岂不是混合了两个层的节点了,怎么去区分呢?针对这个问题,我们其实可以再踢出某层第一个节点之前,先计算队列中的节点个数,这样,由于队列是先入先出的,并且是有序的,所以,我们按照提前计算的队列中某层的节点个数,去执行“踢出”操作,就可以解决这个问题了。

那怎样去判断是最底层的节点呢?既然我们将每层的节点都放到了队列中,那么,如果队列中没有元素了,就代表我们刚刚遍历的就是最底层的节点了。所以,在遍历每一层的时候,我们都需要统计这一层的总和,只是说,每层的总和我们只会使用一个变量int result;当我们计算完第N层的总和只后,我们会直接赋值给result,也就相当于第N层的总和覆盖了第N-1层的总和。

好了,思路基本讲完了,我们以root = [1,2,3,4,5,6,null,7,null,null,null,null,8]为例,看看具体是怎样操作的。

首先,我们将root节点放入到队列deque中,然后进入while(!deque.isEmpty())循环中,在循环的逻辑中,我们首先计算deque中元素的个数,其实也就是计算第0层节点的个数,deque.size()等于1,那么我们只需要将Node(1)从队列中“踢出”即可,计算该层总和result=1,并将其左右子节点放入到队列中(即:Node(2)和Node(3))

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)_算法_02

上面我们遍历完第0层的节点,我们下面继续遍历第1层的节点。与上面步骤一样,我们首先获得队列中的节点个数,此时节点个数为2(即:Node(2)和Node(3)),也就是表明我们要遍历队列中的2个节点。这时候,我们先将Node(2)踢出队列,并将其左右子节点放入队列中(Node(4)和Node(5)),那么此时队列中包含了3个节点——Node(3)Node(4)Node(5),那么这个情况就是我们上面提到的一个队列中保存了多个层级的节点。由于Node(2)的值为2,所以第1层的节点总和暂时为2;接着我们“踢出”Node(3),将其左子节点Node(6)放入到队列中,由于它没有右子节点,所以不用处理。由于节点Node(3)出队列了,并且Node(6)如队列了,那么此时队列中包含了3个节点——Node(4)Node(5)Node(6),正好是第2层的所有节点。此时,计算第1层总和为2+3=5。具体操作,请见下图:

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)_广度优先_03

对于第2层第3层的操作逻辑,跟上面类似,此处就不赘述了。我们直接看下图的具体操作就可以了:

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)_算法_04

针对于广度优先算法的具体代码实现,请参照:1> 实现1:广度优先算法

4.2> 思路2:深度优先算法

一般来说,广度优先算法的问题,同样也可以采用了深度优先算法去解答。在深度优先算法的中,我们不再需要队列的支持,只需要遍历maxLevel去记录当前的“最大层次”,为什么是“当前”呢?就是因为我们在深度优先算法中,是以某一条分支去遍历的,所以,当我们发现当前的层数大于了maxLevel的时候,我们就要将maxLevel更新为当前层数,同时重置result属性。

那么,当我们遍历的叶子节点所在的层数小于maxLevel,那么,恭喜你,我们什么都不需要去做了。如果我们发现当前叶子节点等于maxLevel,那么我们就开始将该节点的val值加到result变量上进行层级节点的统计操作。

现在,我们还是以root = [1,2,3,4,5,6,null,7,null,null,null,null,8]为例,深度优先算法的具体操作,请参照下图所示:

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)_广度优先_05

针对于深度优先算法的具体代码实现,请参照:2> 实现2:深度优先算法

四、代码实现

4.1> 实现1:广度优先算法

class Solution {
    public int deepestLeavesSum(TreeNode root) {
        int result = 0;
		Queue<TreeNode> deque = new ArrayDeque();
        deque.offer(root);
        while(!deque.isEmpty()){
            result = 0;
            int nums = deque.size();
            for(int i = 0; i < nums; i++){
                TreeNode node = deque.poll();
                if(node.left != null) deque.offer(node.left);
                if(node.right != null) deque.offer(node.right);
                result += node.val;
            }
        }
        return result;
    }
}

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)_子节点_06

4.2> 实现2:深度优先算法

class Solution {
    int result = 0, maxLevel = 0;
    public int deepestLeavesSum(TreeNode root) {       
        calculate(root, maxLevel);
        return result;
    }
    public void calculate(TreeNode node, int level) {
        if (level > maxLevel) {
            maxLevel = level;
            result = node.val;
        } else if (level == maxLevel) {
            result += node.val;
        } 
        if (node.left != null) calculate(node.left, level + 1);
        if (node.right != null) calculate(node.right, level + 1);
    }
}

图解LeetCode——1302. 层数最深叶子节点的和(难度:中等)_后端_07

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

举报

相关推荐

0 条评论