题目来源:https://leetcode-cn.com/problems/count-nodes-with-the-highest-score/
大致题意:
给一个二叉树,求出去掉任意节点后可以得到的最高分的个数
- 去掉节点的得分计算方法为:去掉节点形成的所有子树的节点个数相乘的乘积
思路
去掉一个节点后,若其为根节点,那么最多形成左右两颗子树,若不是根节点,那么最多形成左右两颗子树加上包含根节点的子树
于是可以用 dfs 求出左右子树的节点数,然后使用**节点总数减去子树节点数再减 1(当前节点本身)**就可以得到包含根节点的子树的节点数,三数相乘即为该节点去掉的得分
dfs
- 根据给定的数组求出每个节点的子节点
- dfs 遍历,求出所有点的得分,并统计最高得分
代码:
public class CountHighestScoreNodes {
long max; // 最高分
int n; // 节点总数
int count; // 最高分的个数
List<Integer>[] children; // 存节点的子节点
public int countHighestScoreNodes(int[] parents) {
// 初始化
n = parents.length;
children = new List[n];
max = 0;
count = 0;
for (int i = 0; i < n; i++) {
children[i] = new ArrayList<>();
}
// 求出每个节点的子节点
for (int i = 1; i < n; i++) {
children[parents[i]].add(i);
}
// 求出得分
dfs(0);
return count;
}
public int dfs(int node) {
// 默认得分为 1
long score = 1;
// 存包含根节点的子树节点数目,初始时为 总数 - 1
int size = n - 1;
for (int i = 0; i < children[node].size(); i++) {
// 获取子节点
int child = children[node].get(i);
// 获取子树的节点数
int childScore = dfs(child);
// 统计得分
score *= childScore;
// 更新包含根节点的子树节点数目
size -= childScore;
}
// 若不为根节点,得分乘上包含根节点的子树节点数目
if (node != 0) {
score *= size;
}
// 更新最高分以及对应个数
if (score == max) {
count++;
} else if (score > max) {
max = score;
count = 1;
}
// 返回包含当前节点的子树节点个数
return n - size;
}
}