Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
不是因为看到了希望才坚持,而是因为坚持了才能看到希望。共勉
每日刷题第61天 2021.03.11
2049. 统计最高分的节点数目
- leetcode原题链接:leetcode-cn.com/problems/co…
- 难度:困难
- 方法:建图+DFS
题目描述
- 给你一棵根节点为 0 的 二叉树 ,它总共有 n 个节点,节点编号为 0 到 n - 1 。同时给你一个下标从 0 开始的整数数组 parents 表示这棵树,其中 parents[i] 是节点 i 的父节点。由于节点 0 是根,所以 parents[0] == -1 。
- 一个子树的 大小 为这个子树内节点的数目。每个节点都有一个与之关联的 分数 。求出某个节点分数的方法是,将这个节点和与它相连的边全部 删除 ,剩余部分是若干个 非空 子树,这个节点的 分数 为所有这些子树 大小的乘积 。
- 请你返回有 最高得分 节点的 数目 。
提示
- n == parents.length
- 2 <= n <= 105
- parents[0] == -1
- 对于 i != 0 ,有 0 <= parents[i] <= n - 1
- parents 表示一棵二叉树。
解题思路
- 由于“树”的性质是,每去掉一条边,就会增加一个连通分量,因此去掉的边数等于得到的子树数量 + * 注意到去掉一个结点本身所连的边的时候,最多将整个树分为四个子树:结点本身、左子树、右子树、父节点的剩下部分。为了计算每个结点的“分数”,我们只需要计算左子树、右子树和父结点部分的大小即可。
- 要得到这些信息,我们只需要知道以每个结点为根的树的大小,那么一个结点的分数为:以左子结点为根的树大小 × 以右子结点为根的树大小 × (整个树大小 − 以当前结点为根的树大小),以左子结点为根的树大小×以右子结点为根的树大小×(整个树大小−以当前结点为根的树大小)
- 而:以一个结点为根的树的大小 = 以左子结点为根的树大小 + 以右子结点为根的树大小 +
1,以一个结点为根的树的大小=以左子结点为根的树大小+以右子结点为根的树大小+1
- 计算一个结点为根的树大小,需要依赖于两个子树,因此我们需要将树进行拓扑排序,然后再按从叶子到根的顺序计算。本例使用
DFS进行拓扑排序。
AC代码
var countHighestScoreNodes = function (parents) {
for (let i = 0; i < parents.length; i++) {
const item = parents[i];
if (i > 0) {
obj[i].parent = obj[item]
if (obj[item].left) {
obj[item].right = obj[i]
} else {
obj[item].left = obj[i]
}
}
}
function search(node) {
if (node.left !== null) {
let leftCounter = search(node.left)
node.leftCounter = Math.max(node.leftCounter, leftCounter)
}
if (node.right !== null) {
let rightCounter = search(node.right)
node.rightCounter = Math.max(node.rightCounter, rightCounter)
}
return node.leftCounter + node.rightCounter + 1
}
search(obj[0])
let max = 0
let arr = []
for (let i = 0; i < parents.length; i++) {
const item = obj[i]
let temp = 0
if (i === 0) {
temp = (item.leftCounter || 1) * (item.rightCounter || 1)
} else {
if (item.parent.left === item) {
temp = (item.leftCounter || 1) * (item.rightCounter || 1) * (parents.length - (item.leftCounter + item.rightCounter + 1))
} else {
temp = (item.leftCounter || 1) * (item.rightCounter || 1) * (parents.length - (item.leftCounter + item.rightCounter + 1))
}
}
max = Math.max(temp, max)
arr.push(temp)
}
return arr.reduce((sum, item) => {
item === max && (sum++)
return sum
}, 0)
};
总结
- 建图的过程中,还存在一些问题,需要多注意
- 例如建图的左右节点的方式