📜  找到二叉树的两个叶子之间的最大路径和(1)

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

找到二叉树的两个叶子之间的最大路径和

当给定一棵二叉树时,我们可以找到它的两个叶子节点之间的所有路径并计算它们的权重之和。在此问题中,我们要寻找的是二叉树中两个叶子节点之间的最大路径和,即一条路径的权重是从起始节点到终止节点的所有节点的权重之和。

方法1:DFS

我们可以使用DFS(深度优先搜索)来解决此题目。我们可以先遍历左子树和右子树,并计算它们的最大路径和。然后,我们可以将左子树和右子树的最大路径和加起来,得到一条经过父节点的路径。如果这条路径的权重大于我们目前找到的最大路径权重,则更新最大路径权重。最后,我们返回一条从根节点到叶子节点的路径的权重之和以及最大路径权重。这是因为我们只需要从根节点开始计算所有可能的路径。

以下就是基于DFS的解答:

# Python 3
class Solution:
    def maxPathSum(self, root: TreeNode) -> int:
        # 用于存储最大路径权重的变量
        self.max_sum = float('-inf')
        # 递归函数,用于计算经过当前节点的最大路径权重
        def dfs(node):
            # 如果当前节点为空,则返回0
            if not node:
                return 0
            # 计算左子树和右子树的最大路径和
            left_sum = max(0, dfs(node.left))
            right_sum = max(0, dfs(node.right))
            # 更新当前节点作为路径中间节点的最大路径和
            self.max_sum = max(self.max_sum, left_sum + right_sum + node.val)
            # 返回从当前节点到下一个节点的最大路径和
            return max(left_sum, right_sum) + node.val
        # 递归从根节点开始计算最大路径权重
        dfs(root)
        return self.max_sum

代码解释:

  1. 定义了一个类 Solution,这个类有一个方法 maxPathSum,输入为一个二叉树的根节点,输出为一个整数。
  2. 初始时将 self.max_sum 设为 float('-inf'),表示最大路径和还未被计算。
  3. 定义了一个内部递归函数 dfs,输入为一个二叉树节点,输出为一个整数,表示从当前节点到下一个节点的最大路径和。
  4. 在 dfs 函数中,如果当前节点为空,则返回0。
  5. 分别计算当前节点左子树和右子树的最大路径和(用 max(0, x) 的原因在于,如果子节点的路径和为负数,则不计算该节点)。
  6. 更新当前节点作为路径中间节点的最大路径和(加node.val的原因在于将当前节点计入路径路径和)。
  7. 返回从当前节点到下一个节点的最大路径和。
  8. 在主函数中,从根节点开始递归计算最大路径权重,然后返回 self.max_sum。

时间复杂度:O(n),每个节点会被遍历一次,且dfs的时间复杂度为O(1)。因此,总时间复杂度为O(n)。

方法2:BFS

除了DFS,我们也可以使用BFS(广度优先搜索)来解决这个问题。我们可以按层遍历每个节点,如果一个节点是叶子节点,则将它的路径和与目前的最大路径和进行比较。

以下是基于 BFS 的代码解答:

# Python 3
class Solution:
    def maxPathSum(self, root: TreeNode) -> int:
        # 用于存储最大路径权重的变量
        max_sum = float('-inf')
        # 建立队列并将根节点入队,同时存储该节点到根节点的路径和
        queue = [(root, root.val)]
        # BFS
        while queue:
            node, current_sum = queue.pop(0)
            # 如果当前节点是叶子节点,则更新最大路径权重
            if not node.left and not node.right:
                max_sum = max(max_sum, current_sum)
            # 将当前节点的左子节点加入队列,并更新左子节点到根节点的路径和
            if node.left:
                queue.append((node.left, current_sum + node.left.val))
            # 将当前节点的右子节点加入队列,并更新右子节点到根节点的路径和
            if node.right:
                queue.append((node.right, current_sum + node.right.val))
        return max_sum

代码解释:

  1. 定义了一个类 Solution,这个类有一个方法 maxPathSum,输入为一个二叉树的根节点,输出为一个整数。
  2. 初始时将 max_sum 设为 float('-inf'),表示最大路径和还未被计算。
  3. 建立一个队列 queue,并将二叉树的根节点和该节点到根节点的路径和放入队列中。
  4. 在 while 循环中,每次从队列的最前面取出一个节点和该节点到根节点的路径和。
  5. 如果该节点为叶子节点,则更新 max_sum(这里没有使用DFS中的内部函数,是因为我们需要不止一次更新max_sum,而内部函数只允许一次更新)。
  6. 将该节点的左子节点和右子节点加入队列,并更新它们到根节点的路径和。
  7. 返回最大路径和 max_sum。

时间复杂度:O(n),每个节点会被遍历一次,且每个节点的左子节点和右子节点在遍历过程中都会入队一次,因此总时间复杂度为O(n)。

总结:

这两种方法都是遍历整棵树并比较权重相加,时间复杂度都是 O(n)。因此,我们可以使用任一种算法来解决这个问题。

在此,我们建议使用DFS,因为它有许多优势。DFS可以在不占用额外空间的情况下解决这个问题,并且只需要遍历整棵树一次。此外,DFS使程序员易于理解代码的执行顺序,因为程序员能够很清楚地看到在遍历树的过程中,程序是如何向下移动以及如何计算最大路径和的。