📜  门| GATE CS 2018 |简体中文问题28(1)

📅  最后修改于: 2023-12-03 15:42:11.847000             🧑  作者: Mango

门 | GATE CS 2018 |简体中文问题28

题目描述

给定一棵二叉树的根节点,每个节点有一个权值。定义一个节点的权值为它到根节点的路径上所有节点权值之和。请编写一个算法,找到树中权值最大的节点。

输入

输入有两行。第一行包含一个整数 $n$,表示二叉树中的节点个数 $(1 \leq n \leq 10^4)$。第二行包含 $n$ 个整数,表示每个节点的权值 $(1 \leq w_i \leq 1000)$。接下来 $n-1$ 行,每行包含两个整数 $u$ 和 $v$,表示有一条从节点 $u$ 到节点 $v$ 的边。

输出

输出一个整数,表示树中权值最大的节点的权值。如果存在多个节点权值最大,输出其中编号最小的节点。

示例
输入
5
1 3 2 5 1
1 2
1 3
2 4
2 5
输出
11
解释

节点 4 的权值为 $1+3+2 = 6$,节点 5 的权值为 $1+3+1 = 5$,节点 2 的权值为 $1+3 = 4$,节点 3 的权值为 $1+2 = 3$,节点 1 的权值为 $1$。因此,节点 4 的权值最大,为 6。

解题思路

本题需要找到树中权值最大的节点。由题可知,一个节点的权值为它到根节点的路径上所有节点的权值之和。因此,我们可以从根节点开始逐个遍历所有节点,并计算出每个节点的权值,最终找到权值最大的节点。

遍历二叉树可以使用深度优先搜索(DFS)或广度优先搜索(BFS)。本题采用 DFS 来遍历整棵树。从根节点开始遍历,如果当前节点是叶节点(即没有子节点),则将当前节点的权值返回。否则,分别遍历当前节点的左子树和右子树,计算出左右子树中权值最大的节点的权值,加上当前节点的权值,即可得到当前节点的权值。最后比较左右子树和当前节点的权值,返回其中最大的一个。根据这个规则,递归遍历整棵树,即可得到树中权值最大的节点。

代码实现
def max_weight_node(root):
    if not root:  # 如果根节点为空,返回0
        return 0
    if not root.left and not root.right:  # 如果当前节点是叶节点,返回它的权值
        return root.val
    max_left = max_weight_node(root.left)  # 遍历左子树,计算出左子树中权值最大的节点的权值
    max_right = max_weight_node(root.right)  # 遍历右子树,计算出右子树中权值最大的节点的权值
    current = max(max_left, max_right) + root.val  # 当前节点的权值等于左右子树中权值最大的节点的权值加上当前节点的权值
    return max(current, max_left, max_right)  # 返回左右子树和当前节点中权值最大的节点的权值

代码中的 root 表示树的根节点,root.leftroot.right 分别表示根节点的左子树和右子树。如果当前节点是叶节点,则返回当前节点的权值 root.val。否则,分别递归遍历左子树和右子树,并计算出左右子树中权值最大的节点的权值 max_leftmax_right。然后,将最大值加上当前节点的权值,得到当前节点的权值 current。最后,比较左右子树和当前节点的权值,返回其中最大的一个。

总结

本题实际上是一道树的遍历题,需要采用 DFS 或 BFS 遍历整棵树。由于树的节点数最多为 $10^4$,因此时间复杂度最好为 $O(n)$,最坏为 $O(n^2)$,其中 $n$ 表示树的节点数。本文给出了一种基于 DFS 的解法,时间复杂度为 $O(n)$,空间复杂度为 $O(n)$。