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

一、题目

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

二、示例

2.1> 示例1

【输入】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))

上面我们遍历完第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。具体操作,请见下图:

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

针对于广度优先算法的具体代码实现,请参照: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]为例,深度优先算法的具体操作,请参照下图所示:

针对于深度优先算法的具体代码实现,请参照: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;
    }
}

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);
    }
}

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

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

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整组 nums 和一个目标值 target,要组中找出两个的和等于目标值,并返回这两个的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历组的所有组合,判断两个的和是否等于目标值。如果等于目标值,则返回这两个的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储组中的元素和对应的索引。遍历组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果组已经排序,可以使用双指针的方法来解。假设组从小到大排序,定义左指针left指向组的第一个元素,右指针right指向组的最后一个元素。 如果当前两个指针指向的的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要。如果组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值