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

📅  最后修改于: 2022-05-13 01:57:21.125000             🧑  作者: Mango

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

给定一棵二叉树,其中每个节点元素都包含一个数字。找到从一个叶节点到另一个叶节点的最大可能总和。
最大和路径可能会或可能不会通过根。例如,在下面的二叉树中,最大和为27 (3 + 6 + 9 + 0 – 1 + 10)。预期时间复杂度为 O(n)。
如果根的一侧为空,则函数应返回负无穷大(在 C/C++ 的情况下为 INT_MIN)

树

一个简单的解决方案是遍历树并对每个遍历的节点 X 进行跟踪。
1)在 X 的左子树中找到从叶子到根的最大和(我们可以使用这篇文章进行此步骤和后续步骤)
2) 在 X 的右子树中找到从叶子到根的最大和。
3)将以上两个计算值和X->data相加,将和与目前得到的最大值进行比较,更新最大值。
4) 返回最大值。
上述解决方案的时间复杂度为 O(n 2 )
我们可以使用二叉树的单次遍历找到最大和。这个想法是在递归调用中保持两个值

(注意:如果树是最右边或最左边的树,那么首先我们必须调整树,使左右都不为空。最左边的意思是如果树的超级根的右边为空,并且最右边的树意味着如果树的超级根的左边为空。)

1) 以当前节点为根的子树的最大根到叶路径和。
2)叶子之间的最大路径和(期望的输出)。
对于每个访问过的节点 X,我们在 X 的左子树和右子树中找到最大根到叶总和。我们将两个值与 X->data 相加,并将总和与迄今为止找到的最大路径总和进行比较。

以下是上述 O(n) 解决方案的实现。

C++
// C++ program to find maximum path
//sum between two leaves of  a binary tree
#include 
using namespace std;
 
// A binary tree node
struct Node
{
    int data;
    struct Node* left, *right;
};
 
// Utility function to allocate memory for a new node
struct Node* newNode(int data)
{
    struct Node* node = new(struct Node);
    node->data = data;
    node->left = node->right = NULL;
    return (node);
}
 
// Utility function to find maximum of two integers
int max(int a, int b)
{ return (a >= b)? a: b; }
 
// A utility function to find the maximum sum between any
// two leaves.This function calculates two values:
// 1) Maximum path sum between two leaves which is stored
//    in res.
// 2) The maximum root to leaf path sum which is returned.
// If one side of root is empty, then it returns INT_MIN
int maxPathSumUtil(struct Node *root, int &res)
{
    // Base cases
    if (root==NULL) return 0;
    if (!root->left && !root->right) return root->data;
 
    // Find maximum sum in left and right subtree. Also
    // find maximum root to leaf sums in left and right
    // subtrees and store them in ls and rs
    int ls = maxPathSumUtil(root->left, res);
    int rs = maxPathSumUtil(root->right, res);
 
 
    // If both left and right children exist
    if (root->left && root->right)
    {
        // Update result if needed
        res = max(res, ls + rs + root->data);
 
        // Return maximum possible value for root being
        // on one side
        return max(ls, rs) + root->data;
    }
 
    // If any of the two children is empty, return
    // root sum for root being on one side
    return (!root->left)? rs + root->data:
                          ls + root->data;
}
 
// The main function which returns sum of the maximum
// sum path between two leaves. This function mainly
// uses maxPathSumUtil()
int maxPathSum(struct Node *root)
{
    int res = INT_MIN;
   
    int val = maxPathSumUtil(root, res);
           
      //--- for test case ---
   //         7                
      //        /    \              
    //    Null   -3           
      //     (case - 1)        
      //   value of res will be INT_MIN but the answer is 4 , which is returned by the
      // function maxPathSumUtil().
   
      if(res == INT_MIN)
    {
      return val;
    }
   
    return res;
}
 
// Driver Code
int main()
{
    struct Node *root = newNode(-15);
    root->left = newNode(5);
    root->right = newNode(6);
    root->left->left = newNode(-8);
    root->left->right = newNode(1);
    root->left->left->left = newNode(2);
    root->left->left->right = newNode(6);
    root->right->left = newNode(3);
    root->right->right = newNode(9);
    root->right->right->right= newNode(0);
    root->right->right->right->left= newNode(4);
    root->right->right->right->right= newNode(-1);
    root->right->right->right->right->left= newNode(10);
    cout << "Max pathSum of the given binary tree is "
         << maxPathSum(root);
    return 0;
}


Java
// Java program to find maximum path sum between two leaves
// of a binary tree
class Node {
 
    int data;
    Node left, right;
 
    Node(int item) {
        data = item;
        left = right = null;
    }
}
 
// An object of Res is passed around so that the
// same value can be used by multiple recursive calls.
class Res {
    int val;
}
 
class BinaryTree {
 
    static Node root;
      Node setTree(Node root){
       
      Node temp = new Node(0);
      //if tree is left most
      if(root.right==null){
          root.right=temp;
      }
      else{    //if tree is right most
          root.left=temp;
      }
       
      return root;
    }
 
    // A utility function to find the maximum sum between any
    // two leaves.This function calculates two values:
    // 1) Maximum path sum between two leaves which is stored
    //    in res.
    // 2) The maximum root to leaf path sum which is returned.
    // If one side of root is empty, then it returns INT_MIN
    int maxPathSumUtil(Node node, Res res) {
 
        // Base cases
        if (node == null)
            return 0;
        if (node.left == null && node.right == null)
            return node.data;
 
        // Find maximum sum in left and right subtree. Also
        // find maximum root to leaf sums in left and right
        // subtrees and store them in ls and rs
        int ls = maxPathSumUtil(node.left, res);
        int rs = maxPathSumUtil(node.right, res);
 
        // If both left and right children exist
        if (node.left != null && node.right != null) {
 
            // Update result if needed
            res.val = Math.max(res.val, ls + rs + node.data);
 
            // Return maximum possible value for root being
            // on one side
            return Math.max(ls, rs) + node.data;
        }
 
        // If any of the two children is empty, return
        // root sum for root being on one side
        return (node.left == null) ? rs + node.data
                : ls + node.data;
    }
 
    // The main function which returns sum of the maximum
    // sum path between two leaves. This function mainly
    // uses maxPathSumUtil()
    int maxPathSum(Node node)
    {
        Res res = new Res();
        res.val = Integer.MIN_VALUE;
       
          if(root.left==null || root.right==null){
            root=setTree(root);
        }
          //if tree is left most or right most
          //call setTree() method to adjust tree first
        maxPathSumUtil(root, res);
        return res.val;
    }
 
    //Driver program to test above functions
    public static void main(String args[]) {
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(-15);
        tree.root.left = new Node(5);
        tree.root.right = new Node(6);
        tree.root.left.left = new Node(-8);
        tree.root.left.right = new Node(1);
        tree.root.left.left.left = new Node(2);
        tree.root.left.left.right = new Node(6);
        tree.root.right.left = new Node(3);
        tree.root.right.right = new Node(9);
        tree.root.right.right.right = new Node(0);
        tree.root.right.right.right.left = new Node(4);
        tree.root.right.right.right.right = new Node(-1);
        tree.root.right.right.right.right.left = new Node(10);
        System.out.println("Max pathSum of the given binary tree is "
                + tree.maxPathSum(root));
    }
}
 
// This code is improved by Rahul Soni


Python3
# Python program to find maximumpath sum between two leaves
# of a binary tree
 
INT_MIN = -2**32
 
# A binary tree node
 
 
class Node:
    # Constructor to create a new node
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# Utility function to find maximum sum between any
# two leaves. This function calculates two values:
# 1) Maximum path sum between two leaves which are stored
#    in res
# 2) The maximum root to leaf path sum which is returned
# If one side of root is empty, then it returns INT_MIN
 
 
def maxPathSumUtil(root, res):
 
    # Base Case
    if root is None:
        return 0
 
    # Find maximumsum in left and right subtree. Also
    # find maximum root to leaf sums in left and right
    # subtrees ans store them in ls and rs
    ls = maxPathSumUtil(root.left, res)
    rs = maxPathSumUtil(root.right, res)
 
    # If both left and right children exist
    if root.left is not None and root.right is not None:
 
        # update result if needed
        res[0] = max(res[0], ls + rs + root.data)
 
        # Return maximum possible value for root being
        # on one side
        return max(ls, rs) + root.data
 
    # If any of the two children is empty, return
    # root sum for root being on one side
    if root.left is None:
        return rs + root.data
    else:
        return ls + root.data
 
# The main function which returns sum of the maximum
# sum path betwee ntwo leaves. THis function mainly
# uses maxPathSumUtil()
 
 
def maxPathSum(root):
    res = [INT_MIN]
    maxPathSumUtil(root, res)
    return res[0]
 
 
# Driver program to test above function
root = Node(-15)
root.left = Node(5)
root.right = Node(6)
root.left.left = Node(-8)
root.left.right = Node(1)
root.left.left.left = Node(2)
root.left.left.right = Node(6)
root.right.left = Node(3)
root.right.right = Node(9)
root.right.right.right = Node(0)
root.right.right.right.left = Node(4)
root.right.right.right.right = Node(-1)
root.right.right.right.right.left = Node(10)
 
print ("Max pathSum of the given binary tree is", maxPathSum(root))
 
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)


C#
using System;
 
// C# program to find maximum path sum between two leaves
// of a binary tree
public class Node
{
 
    public int data;
    public Node left, right;
 
    public Node(int item)
    {
        data = item;
        left = right = null;
    }
}
 
// An object of Res is passed around so that the
// same value can be used by multiple recursive calls.
public class Res
{
    public int val;
}
 
public class BinaryTree
{
 
    public static Node root;
 
    // A utility function to find the maximum sum between any
    // two leaves.This function calculates two values:
    // 1) Maximum path sum between two leaves which is stored
    //    in res.
    // 2) The maximum root to leaf path sum which is returned.
    // If one side of root is empty, then it returns INT_MIN
    public virtual int maxPathSumUtil(Node node, Res res)
    {
 
        // Base cases
        if (node == null)
        {
            return 0;
        }
        if (node.left == null && node.right == null)
        {
            return node.data;
        }
 
        // Find maximum sum in left and right subtree. Also
        // find maximum root to leaf sums in left and right
        // subtrees and store them in ls and rs
        int ls = maxPathSumUtil(node.left, res);
        int rs = maxPathSumUtil(node.right, res);
 
        // If both left and right children exist
        if (node.left != null && node.right != null)
        {
 
            // Update result if needed
            res.val = Math.Max(res.val, ls + rs + node.data);
 
            // Return maximum possible value for root being
            // on one side
            return Math.Max(ls, rs) + node.data;
        }
 
        // If any of the two children is empty, return
        // root sum for root being on one side
        return (node.left == null) ? rs + node.data : ls + node.data;
    }
 
    // The main function which returns sum of the maximum
    // sum path between two leaves. This function mainly
    // uses maxPathSumUtil()
    public virtual int maxPathSum(Node node)
    {
        Res res = new Res();
        res.val = int.MinValue;
        maxPathSumUtil(root, res);
        return res.val;
    }
 
    //Driver program to test above functions
    public static void Main(string[] args)
    {
        BinaryTree tree = new BinaryTree();
        BinaryTree.root = new Node(-15);
        BinaryTree.root.left = new Node(5);
        BinaryTree.root.right = new Node(6);
        BinaryTree.root.left.left = new Node(-8);
        BinaryTree.root.left.right = new Node(1);
        BinaryTree.root.left.left.left = new Node(2);
        BinaryTree.root.left.left.right = new Node(6);
        BinaryTree.root.right.left = new Node(3);
        BinaryTree.root.right.right = new Node(9);
        BinaryTree.root.right.right.right = new Node(0);
        BinaryTree.root.right.right.right.left = new Node(4);
        BinaryTree.root.right.right.right.right = new Node(-1);
        BinaryTree.root.right.right.right.right.left = new Node(10);
        Console.WriteLine("Max pathSum of the given binary tree is " + tree.maxPathSum(root));
    }
}
 
  // This code is contributed by Shrikant13


Javascript


输出
Max pathSum of the given binary tree is 27

感谢 Saurabh Vats 建议对原始方法进行更正。

此代码由 Rahul Soni 改进。