2049. 统计最高分的节点数目

Posted Debroon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2049. 统计最高分的节点数目相关的知识,希望对你有一定的参考价值。

2049. 统计最高分的节点数目

 


题目

传送门:https://leetcode.cn/problems/count-nodes-with-the-highest-score/

 


算法设计:深度优先搜索

这题的核心是计算分数。

一个节点的分数 = 左子树节点数 × 右子树节点数 × 除自己外其他节点数。如下图:

删除某个节点之后,最多会把二叉树分割成 三个部分 :左子树、右子树、父节点及父节点的另一半子树(除自己外其他节点个数)。

使用 DFS 算出左子树节点数、右子树节点数。

因为知道树节点的总数,再计算除自己外其他节点个数。

  • 除自己外其他节点个数 = 总数 - 1 - 左子树节点数 - 右子树节点数。

具体怎么解呢?

一个节点的分数 = 左子树节点数 × 右子树节点数 × 除自己外其他节点数

  • 一是,需要清晰左子树节点数、右子树节点数,再通过总数 - 左右子树数 - 1,得到除自己外其他节点数

  • 二是,三个数量都有了之后,相乘就是删除这个节点之后的分数,当然,这里有可能三个部分中缺失一部分或者两部分,缺失的部分用 1 来代替去相乘。

  • 最终表达式:一个节点的分数 = 左子树节点数 × 右子树节点数 × (总数 - 左右子树数 - 1)

int dfs(vector<vector<int>> &tree, vector<long> &s, int i)  
	long score = 1, sum = 1;                                       // 分数,节点总数,设置为long防止溢出
	for (int j : tree[i])                                         // 遍历i所有子节点
		int cnt = dfs(tree, s, j);                                 // 得出子树节点个数
		score *= cnt, sum += cnt;                                  // 计算左右子树的数量,同时计算节点总数,累计每个子树节点数量和。因为分数等于三块的乘积,可同时计算节点数量、分数
	 
	s[i] = score * (max(1l, (long)tree.size() - sum));             // 一个节点分数 = 左子树节点数 × 右子树节点数 × (总数 - 左右子树数 - 1)。1l是把1改成long类型
	return i != 0 ? sum : count(begin(s), end(s), *max_element(begin(s), end(s)));    // *max_element查询最大分数,count统计最大分数的个数
 
int countHighestScoreNodes(vector<int>& parents)                  // 题目给的 parents 数组不是树,先建树
	int n = parents.size();
	vector<vector<int>> tree(n);                                   // 用数组存储树
	vector<long> s(n); 
	for (int i = 1; i < n; ++i) tree[parents[i]].push_back(i);     // 根据parents建树,tree[i]存储i的子节点
	return dfs(tree, s, 0);                                        // 在图上dfs计算分数

以上是关于2049. 统计最高分的节点数目的主要内容,如果未能解决你的问题,请参考以下文章

[leetcode] 2049 统计最高分的节点数目 | dfs二叉树

LeetCode 2049统计最高分的节点数目[dfs 二叉树] HERODING的LeetCode之路

LeetCode 2049. 统计最高分的节点数目

leetcode中等2049统计最高分的节点数目

LeetCode 589. N 叉树的前序遍历(迭代写法) / 2049. 统计最高分的节点数目 / 590. N 叉树的后序遍历

统计最高分的节点数目