leetcode
leetcode 951 ~ 1000
最大层内元素和

最大层内元素和

难度:

标签:

题目描述

给你一个二叉树的根节点 root。设根节点位于二叉树的第 1 层,而根节点的子节点位于第 2 层,依此类推。

请返回层内元素之和 最大 的那几层(可能只有一层)的层号,并返回其中 最小 的那个。

 

示例 1:

输入:root = [1,7,0,7,-8,null,null]
输出:2
解释:
第 1 层各元素之和为 1,
第 2 层各元素之和为 7 + 0 = 7,
第 3 层各元素之和为 7 + -8 = -1,
所以我们返回第 2 层的层号,它的层内元素之和最大。

示例 2:

输入:root = [989,null,10250,98693,-89388,null,null,null,-32127]
输出:2

 

提示:

  • 树中的节点数在 [1, 104]范围内
  • -105 <= Node.val <= 105

代码结果

运行时间: 132 ms, 内存: 19.6 MB


/*
 * 思路:
 * 虽然Java Streams不是特别适合处理树结构,但我们依然可以
 * 使用广度优先搜索(BFS)来收集每一层的节点,然后使用
 * Stream API来计算每层的和。
 */

import java.util.*;
import java.util.stream.*;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

class Solution {
    public int maxLevelSum(TreeNode root) {
        if (root == null) return 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int maxSum = Integer.MIN_VALUE;
        int maxLevel = 1;
        int currentLevel = 1;
        while (!queue.isEmpty()) {
            int levelSize = queue.size();
            int levelSum = queue.stream().limit(levelSize).mapToInt(node -> node.val).sum();
            if (levelSum > maxSum) {
                maxSum = levelSum;
                maxLevel = currentLevel;
            }
            for (int i = 0; i < levelSize; i++) {
                TreeNode node = queue.poll();
                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            currentLevel++;
        }
        return maxLevel;
    }
}

解释

方法:

该题解使用了广度优先搜索(BFS)来遍历二叉树的每一层,并计算每一层的节点值之和。算法初始化时,将二叉树的根节点放入队列中。在每一次循环中,算法处理当前队列中的所有节点(即当前层的所有节点),计算这一层的总和,并将其子节点放入下一个队列中,为处理下一层做准备。同时,算法比较当前层的总和与之前记录的最大层的总和,如果当前层的总和更大,则更新最大总和和对应的层号。这一过程持续进行,直到所有层都被处理完毕。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在计算每一层的元素总和时,如果某一层的所有节点都是负数,算法如何处理这种情况?
算法会正常计算这一层所有节点值的总和,即使它们都是负数。然后,它将这一层的总和与之前记录的最大总和进行比较。如果这一层的总和大于目前记录的最大总和,则更新最大总和及对应的层号。如果所有层的总和都是负数,算法仍然会返回具有最大(或者说最不负)总和的层号。
🦆
为什么在遍历树的时候选择使用广度优先搜索(BFS),而不是深度优先搜索(DFS)?
使用广度优先搜索(BFS)可以自然地按层遍历树。这种方法可以让我们简单地在每一层的遍历过程中计算出该层的总和,并轻松更新和比较最大层总和。相对地,深度优先搜索(DFS)需要额外的机制来跟踪节点的层次信息,并且在遍历过程中不断回溯,这会使层次总和的计算和比较变得更加复杂。
🦆
在处理队列时,算法是如何确保它始终包含当前层的所有节点的?
在每一次循环中,算法首先创建一个空的队列nq用来存放下一层的节点。然后,它遍历当前队列q中的所有节点,并将它们的子节点(如果存在)加入到nq中。这确保了当当前层的所有节点被处理完后,nq包含了下一层的所有节点。之后,将q更新为nq,继续下一轮循环,这样每次循环处理的都是同一层的所有节点。
🦆
在算法中,当存在多个层的元素之和相等时,如何保证返回的是最小的层号?
算法在比较层的总和时,只有当找到一个更大的总和时才会更新记录的最大总和和对应的层号。如果当前层的总和与之前记录的最大总和相等,它不会更新层号。这意味着最初记录的那个层号(最小的层号)将被保留,直到找到一个具有更大总和的层。因此,算法自然地保证了在多个层的总和相等时返回最小的层号。

相关问题