统计最高分的节点数目
难度:
标签:
题目描述
给你一棵根节点为 0
的 二叉树 ,它总共有 n
个节点,节点编号为 0
到 n - 1
。同时给你一个下标从 0 开始的整数数组 parents
表示这棵树,其中 parents[i]
是节点 i
的父节点。由于节点 0
是根,所以 parents[0] == -1
。
一个子树的 大小 为这个子树内节点的数目。每个节点都有一个与之关联的 分数 。求出某个节点分数的方法是,将这个节点和与它相连的边全部 删除 ,剩余部分是若干个 非空 子树,这个节点的 分数 为所有这些子树 大小的乘积 。
请你返回有 最高得分 节点的 数目 。
示例 1:
输入:parents = [-1,2,0,2,0] 输出:3 解释: - 节点 0 的分数为:3 * 1 = 3 - 节点 1 的分数为:4 = 4 - 节点 2 的分数为:1 * 1 * 2 = 2 - 节点 3 的分数为:4 = 4 - 节点 4 的分数为:4 = 4 最高得分为 4 ,有三个节点得分为 4 (分别是节点 1,3 和 4 )。
示例 2:
输入:parents = [-1,2,0] 输出:2 解释: - 节点 0 的分数为:2 = 2 - 节点 1 的分数为:2 = 2 - 节点 2 的分数为:1 * 1 = 1 最高分数为 2 ,有两个节点分数为 2 (分别为节点 0 和 1 )。
提示:
n == parents.length
2 <= n <= 105
parents[0] == -1
- 对于
i != 0
,有0 <= parents[i] <= n - 1
parents
表示一棵二叉树。
代码结果
运行时间: 308 ms, 内存: 47.0 MB
// 思路:
// 1. 构建孩子列表。
// 2. 使用递归计算每个节点的子树大小。
// 3. 计算每个节点的分数并统计最高分数的节点数。
// 4. 使用 Java Stream API 进行流处理。
import java.util.*;
import java.util.stream.*;
public class TreeHighestScoreStream {
public int countHighestScoreNodes(int[] parents) {
int n = parents.length;
List<List<Integer>> children = IntStream.range(0, n)
.mapToObj(i -> new ArrayList<Integer>())
.collect(Collectors.toList());
for (int i = 1; i < n; i++) {
children.get(parents[i]).add(i);
}
int[] subtreeSize = new int[n];
dfs(0, children, subtreeSize);
int[] scores = new int[n];
IntStream.range(0, n).forEach(i -> {
int score = 1;
int totalSize = n - 1;
for (int child : children.get(i)) {
score *= subtreeSize[child];
totalSize -= subtreeSize[child];
}
if (i != 0) {
score *= totalSize;
}
scores[i] = score;
});
int maxScore = Arrays.stream(scores).max().orElse(0);
return (int) Arrays.stream(scores).filter(score -> score == maxScore).count();
}
private int dfs(int node, List<List<Integer>> children, int[] subtreeSize) {
int size = 1;
for (int child : children.get(node)) {
size += dfs(child, children, subtreeSize);
}
subtreeSize[node] = size;
return size;
}
}
解释
方法:
该题解采用深度优先搜索(DFS)的方法来解决问题。首先,通过父节点数组构建一个树的子节点列表表示。对每个节点,使用DFS来计算以该节点为根的子树的大小,并计算删除该节点后其他部分的大小乘积作为该节点的得分。在DFS过程中,同时更新最高得分和得分最高的节点数。整体过程避免了重复计算,每个节点只被访问一次,确保了效率。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在构建树的子节点列表时,你是如何确保每个节点都正确地被分配到其父节点的子列表中的?
▷🦆
你的DFS函数是如何确保每个节点只被访问一次的,并且它是怎样避免重复计算的?
▷🦆
为什么在计算节点分数时要初始化分数为1,并在遍历子节点时累乘子树大小?这种方法是否可能导致分数的溢出?
▷🦆
当节点为根节点时,你是如何处理其分数计算的?为什么根节点的处理逻辑与其他节点不同?
▷