Max Path Sum Between Two Leaves

Last Updated : 9 Oct, 2026

Given the root of a binary tree, where each node contains an integer value, find the maximum possible path sum between any two leaf nodes. If the tree has fewer than two leaf nodes, return -1.

Examples:

Input: root = [3, 4, 5, -10, 4, N, N]

a

Output: 16
Explanation:

b

The leaf nodes are -10, 4 (right child of 4), and 5.
Possible paths between leaf nodes are:
-10 -> 4 -> 3 -> 5 = -10 + 4 + 3 + 5 = 2
-10 -> 4 -> 4 = -10 + 4 + 4 = -2
4 -> 4 -> 3 -> 5 = 4 + 4 + 3 + 5 = 16
Hence, the maximum path sum is obtained from the path 4 -> 4 -> 3 -> 5, giving 16.

Input: root = [-15, 5, 6, -8, 1, 3, 9, 2, -3, N, N, N, N, N, 0, N, N, N, N, 4, -1, N, N, 10]

c

Output: 27
Explanation:

d

The leaf nodes are 2, -3, 1, 3, 4, and 10.
Some possible paths between leaves are:
2 -> -8 -> 5 -> 1 = 2 + (-8) + 5 + 1 = 0
-3 -> -8 -> 5 -> 1 = -3 + (-8) + 5 + 1 = -5
2 -> -8 -> 5 -> -15 -> 6 -> 3 = 2 + (-8) + 5 + (-15) + 6 + 3 = -7
1 -> 5 -> -15 -> 6 -> 9 -> 0 -> 4 = 1 + 5 + (-15) + 6 + 9 + 0 + 4 = 10
3 -> 6 -> 9 -> 0 -> -1 -> 10 = 3 + 6 + 9 + 0 + (-1) + 10 = 27
Hence, the maximum path sum is obtained from the path 3 -> 6 -> 9 -> 0 -> -1 -> 10, giving 27.

Input: root = [3, 4, 1, -10, 4, N, N]

e

Output: 12
Explanation:

f

The leaf nodes are -10, 4 (right child of 4), and 1.
Possible paths between leaf nodes are:
-10 -> 4 -> 4 = -10 + 4 + 4 = -2
-10 -> 4 -> 3 -> 1 = -10 + 4 + 3 + 1 = -2
4 -> 4 -> 3 -> 1 = 4 + 4 + 3 + 1 = 12
Hence, the maximum path sum is obtained from the path 4 -> 4 -> 3 -> 1, giving 12.

Try It Yourself
redirect icon

[Naive Approach] Consider Every Pair of Leaves - O(L ^ 2 * n) Time and O(n) Space

The idea is to first collect all leaf nodes and consider every pair of leaves. To find paths sum for a pair do the following.

  • Traverse both nodes from root to find Lowest Common Ancestor LCA.
  • Sum paths from LCA to the both nodes.

Working of the Approach:

  • Traverse the tree and store all the leaf nodes in a list.
  • Consider every possible pair of leaf nodes from this list.
  • For each pair, find the path from the root to both leaves.
  • Compare the two paths to find their Lowest Common Ancestor (LCA), which is the last common node.
  • Calculate the path sum by adding the values from both leaves up to the LCA, including the LCA.
  • Update the maximum path sum if the current path has a larger sum.
  • After checking all pairs, return the maximum path sum found.
C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node *left;
    Node *right;
    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};

bool findPath(Node *root, Node *target, vector<Node*> &path) {
    if (root == nullptr)
        return false;

    path.push_back(root);

    if (root == target)
        return true;

    if (findPath(root->left, target, path) ||
        findPath(root->right, target, path))
        return true;

    path.pop_back();
    return false;
}

void collectLeaves(Node *root, vector<Node*> &leaves) {
    if (root == nullptr)
        return;

    if (root->left == nullptr && root->right == nullptr) {
        leaves.push_back(root);
        return;
    }

    collectLeaves(root->left, leaves);
    collectLeaves(root->right, leaves);
}

int maxPathSum(Node *root) {
    if (root == nullptr)
        return -1;

    vector<Node*> leaves;
    collectLeaves(root, leaves);

    if (leaves.size() < 2)
        return -1;

    int ans = INT_MIN;

    for (int i = 0; i < leaves.size(); i++) {
        for (int j = i + 1; j < leaves.size(); j++) {
            vector<Node*> path1, path2;

            findPath(root, leaves[i], path1);
            findPath(root, leaves[j], path2);

            int k = 0;

            // Find the first different node in both paths.
            while (k < path1.size() && k < path2.size() &&
                   path1[k] == path2[k]) {
                k++;
            }

            int sum = 0;

            // Add the path from the LCA to the first leaf.
            for (int x = k - 1; x < path1.size(); x++)
                sum += path1[x]->data;

            // Add the path from the LCA's child to the second leaf.
            for (int x = k; x < path2.size(); x++)
                sum += path2[x]->data;

            ans = max(ans, sum);
        }
    }

    return ans;
}

int main() {
    Node *root = new Node(3);
    root->left = new Node(4);
    root->right = new Node(5);
    root->left->left = new Node(-10);
    root->left->right = new Node(4);

    cout << maxPathSum(root);

    return 0;
}
Java
import java.util.ArrayList;

class Node {
    int data;
    Node left, right;

    Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG {
    static boolean findPath(Node root, Node target,
                            ArrayList<Node> path)
    {
        if (root == null)
            return false;

        path.add(root);

        if (root == target)
            return true;

        if (findPath(root.left, target, path)
            || findPath(root.right, target, path))
            return true;

        path.remove(path.size() - 1);
        return false;
    }

    static void collectLeaves(Node root,
                              ArrayList<Node> leaves)
    {
        if (root == null)
            return;

        if (root.left == null && root.right == null) {
            leaves.add(root);
            return;
        }

        collectLeaves(root.left, leaves);
        collectLeaves(root.right, leaves);
    }

    static int maxPathSum(Node root)
    {
        if (root == null)
            return -1;

        ArrayList<Node> leaves = new ArrayList<>();
        collectLeaves(root, leaves);

        if (leaves.size() < 2)
            return -1;

        int ans = Integer.MIN_VALUE;

        for (int i = 0; i < leaves.size(); i++) {
            for (int j = i + 1; j < leaves.size(); j++) {
                ArrayList<Node> path1 = new ArrayList<>();
                ArrayList<Node> path2 = new ArrayList<>();

                findPath(root, leaves.get(i), path1);
                findPath(root, leaves.get(j), path2);

                int k = 0;

                // Find the first different node in both
                // paths.
                while (k < path1.size() && k < path2.size()
                       && path1.get(k) == path2.get(k)) {
                    k++;
                }

                int sum = 0;

                for (int x = k - 1; x < path1.size(); x++)
                    sum += path1.get(x).data;

                for (int x = k; x < path2.size(); x++)
                    sum += path2.get(x).data;

                ans = Math.max(ans, sum);
            }
        }

        return ans;
    }

    public static void main(String[] args)
    {
        Node root = new Node(3);
        root.left = new Node(4);
        root.right = new Node(5);
        root.left.left = new Node(-10);
        root.left.right = new Node(4);

        System.out.println(maxPathSum(root));
    }
}
Python
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None


def findPath(root, target, path):
    if root is None:
        return False

    path.append(root)

    if root is target:
        return True

    if findPath(root.left, target, path) or \
       findPath(root.right, target, path):
        return True

    path.pop()
    return False


def collectLeaves(root, leaves):
    if root is None:
        return

    if root.left is None and root.right is None:
        leaves.append(root)
        return

    collectLeaves(root.left, leaves)
    collectLeaves(root.right, leaves)


def maxPathSum(root):
    if root is None:
        return -1

    leaves = []
    collectLeaves(root, leaves)

    if len(leaves) < 2:
        return -1

    ans = float('-inf')

    for i in range(len(leaves)):
        for j in range(i + 1, len(leaves)):
            path1 = []
            path2 = []

            findPath(root, leaves[i], path1)
            findPath(root, leaves[j], path2)

            k = 0

            # Find the first different node in both paths.
            while k < len(path1) and k < len(path2) and \
                  path1[k] is path2[k]:
                k += 1

            currentSum = 0

            for x in range(k - 1, len(path1)):
                currentSum += path1[x].data

            for x in range(k, len(path2)):
                currentSum += path2[x].data

            ans = max(ans, currentSum)

    return ans


if __name__ == "__main__":
    root = Node(3)
    root.left = Node(4)
    root.right = Node(5)
    root.left.left = Node(-10)
    root.left.right = Node(4)

    print(maxPathSum(root))
C#
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG {
    static bool findPath(Node root, Node target,
                         List<Node> path)
    {
        if (root == null)
            return false;

        path.Add(root);

        if (root == target)
            return true;

        if (findPath(root.left, target, path)
            || findPath(root.right, target, path))
            return true;

        path.RemoveAt(path.Count - 1);
        return false;
    }

    static void collectLeaves(Node root, List<Node> leaves)
    {
        if (root == null)
            return;

        if (root.left == null && root.right == null) {
            leaves.Add(root);
            return;
        }

        collectLeaves(root.left, leaves);
        collectLeaves(root.right, leaves);
    }

    static int maxPathSum(Node root)
    {
        if (root == null)
            return -1;

        List<Node> leaves = new List<Node>();
        collectLeaves(root, leaves);

        if (leaves.Count < 2)
            return -1;

        int ans = int.MinValue;

        for (int i = 0; i < leaves.Count; i++) {
            for (int j = i + 1; j < leaves.Count; j++) {
                List<Node> path1 = new List<Node>();
                List<Node> path2 = new List<Node>();

                findPath(root, leaves[i], path1);
                findPath(root, leaves[j], path2);

                int k = 0;

                // Find the Lowest Common Ancestor.
                while (k < path1.Count && k < path2.Count
                       && path1[k] == path2[k]) {
                    k++;
                }

                int sum = 0;

                for (int x = k - 1; x < path1.Count; x++)
                    sum += path1[x].data;

                for (int x = k; x < path2.Count; x++)
                    sum += path2[x].data;

                ans = Math.Max(ans, sum);
            }
        }

        return ans;
    }

    static void Main()
    {
        Node root = new Node(3);
        root.left = new Node(4);
        root.right = new Node(5);
        root.left.left = new Node(-10);
        root.left.right = new Node(4);

        Console.WriteLine(maxPathSum(root));
    }
}
JavaScript
// Finds the path from root to the target leaf.
function findPath(root, target, path) {
    if (root == null)
        return false;

    path.push(root);

    if (root === target)
        return true;

    if (findPath(root.left, target, path) ||
        findPath(root.right, target, path))
        return true;

    path.pop();
    return false;
}

// Collects all leaf nodes of the tree.
function collectLeaves(root, leaves) {
    if (root == null)
        return;

    if (!root.left && !root.right) {
        leaves.push(root);
        return;
    }

    collectLeaves(root.left, leaves);
    collectLeaves(root.right, leaves);
}

function maxPathSum(root) {
    if (root == null)
        return -1;

    let leaves = [];
    collectLeaves(root, leaves);

    if (leaves.length < 2)
        return -1;

    let ans = Number.MIN_SAFE_INTEGER;

    // Check every pair of leaf nodes.
    for (let i = 0; i < leaves.length; i++) {
        for (let j = i + 1; j < leaves.length; j++) {
            let path1 = [];
            let path2 = [];

            findPath(root, leaves[i], path1);
            findPath(root, leaves[j], path2);

            let k = 0;

            // Find the Lowest Common Ancestor.
            while (k < path1.length &&
                   k < path2.length &&
                   path1[k] === path2[k]) {
                k++;
            }

            let sum = 0;

            // Add the path from LCA to the first leaf.
            for (let x = k - 1; x < path1.length; x++)
                sum += path1[x].key;

            // Add the path from LCA's child to the second leaf.
            for (let x = k; x < path2.length; x++)
                sum += path2[x].key;

            ans = Math.max(ans, sum);
        }
    }

    return ans;
}

// Driver code
function Node(x) {
    this.key = x;
    this.left = null;
    this.right = null;
}

let root = new Node(3);
root.left = new Node(4);
root.right = new Node(5);
root.left.left = new Node(-10);
root.left.right = new Node(4);

console.log(maxPathSum(root));

Output
16

[Expected Approach] Postorder DFS - O(n) Time and O(h) Space

The idea is to use postorder traversal to find the maximum sum from each node down to a leaf.

At every node with both left and right children, these two best root-to-leaf paths can be joined to form a leaf-to-leaf path through that node. We update the maximum answer with this path and return the better of the two paths to the parent.

Working of Approach:

  • Traverse the tree using postorder traversal, so both subtrees are processed before their parent.
  • For each node, calculate the maximum path sum from that node down to any leaf.
  • If the node has both children, combine their best sums with the current node's value and update the maximum leaf-to-leaf sum.
  • Return the larger root-to-leaf path sum from the two children to the parent.
  • If the node has only one child, continue through that child and return its path sum along with the current node's value.
  • If no valid path between two leaves exists, return -1.

Let us understand with an example:
Input: root = [3, 4, 5, -10, 4, N, N]

  • Start with the leaf nodes -10, 4, and 5. Each leaf returns its own value.
  • At node 4, the left and right paths give -10 and 4. Their combined path is -10 + 4 + 4 = -2, while the best downward path is 4 + 4 = 8.
  • At node 3, the best paths from its left and right subtrees are 8 and 5. Combining them gives 8 + 3 + 5 = 16.
  • Therefore, the maximum leaf-to-leaf path is 4 -> 4 -> 3 -> 5, with a sum of 16.
C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node *left;
    Node *right;

    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};

int maxPathSumUtil(Node *root, int &res) {
    if (root == nullptr)
        return 0;

    if (root->left == nullptr && root->right == nullptr)
        return root->data;

    int leftSum = maxPathSumUtil(root->left, res);
    int rightSum = maxPathSumUtil(root->right, res);

    if (root->left && root->right) {
        
        // Combine both root-to-leaf paths through the current node.
        res = max(res, leftSum + rightSum + root->data);
        return max(leftSum, rightSum) + root->data;
    }

    if (root->left)
        return leftSum + root->data;

    return rightSum + root->data;
}

int maxPathSum(Node *root) {
    if (root == nullptr)
        return -1;

    int res = INT_MIN;
    maxPathSumUtil(root, res);

    return res == INT_MIN ? -1 : res;
}

int main() {
    Node *root = new Node(3);
    root->left = new Node(4);
    root->right = new Node(5);
    root->left->left = new Node(-10);
    root->left->right = new Node(4);

    cout << maxPathSum(root);

    return 0;
}
Java
class Node {
    int data;
    Node left, right;

    Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG {
    static int maxPathSumUtil(Node root, int[] res)
    {
        if (root == null)
            return 0;

        if (root.left == null && root.right == null)
            return root.data;

        int leftSum = maxPathSumUtil(root.left, res);
        int rightSum = maxPathSumUtil(root.right, res);

        if (root.left != null && root.right != null) {
            // Combine both root-to-leaf paths through the
            // current node.
            res[0] = Math.max(res[0], leftSum + rightSum
                                          + root.data);
            return Math.max(leftSum, rightSum) + root.data;
        }

        if (root.left != null)
            return leftSum + root.data;

        return rightSum + root.data;
    }

    static int maxPathSum(Node root)
    {
        if (root == null)
            return -1;

        int[] res = { Integer.MIN_VALUE };
        maxPathSumUtil(root, res);

        return res[0] == Integer.MIN_VALUE ? -1 : res[0];
    }

    public static void main(String[] args)
    {
        Node root = new Node(3);
        root.left = new Node(4);
        root.right = new Node(5);
        root.left.left = new Node(-10);
        root.left.right = new Node(4);

        System.out.println(maxPathSum(root));
    }
}
Python
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None


def maxPathSumUtil(root, res):
    if root is None:
        return 0

    if root.left is None and root.right is None:
        return root.data

    leftSum = maxPathSumUtil(root.left, res)
    rightSum = maxPathSumUtil(root.right, res)

    if root.left and root.right:
        # Combine both root-to-leaf paths through the current node.
        res[0] = max(res[0], leftSum + rightSum + root.data)
        return max(leftSum, rightSum) + root.data

    if root.left:
        return leftSum + root.data

    return rightSum + root.data


def maxPathSum(root):
    if root is None:
        return -1

    res = [float('-inf')]
    maxPathSumUtil(root, res)

    return -1 if res[0] == float('-inf') else res[0]


if __name__ == "__main__":
    root = Node(3)
    root.left = Node(4)
    root.right = Node(5)
    root.left.left = Node(-10)
    root.left.right = Node(4)

    print(maxPathSum(root))
C#
using System;

class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG {

    static int maxPathSumUtil(Node root, ref int res)
    {
        if (root == null)
            return 0;

        if (root.left == null && root.right == null)
            return root.data;

        int leftSum = maxPathSumUtil(root.left, ref res);
        int rightSum = maxPathSumUtil(root.right, ref res);

        if (root.left != null && root.right != null) {
            // Combine both root-to-leaf paths through the
            // current node.
            res = Math.Max(res,
                           leftSum + rightSum + root.data);
            return Math.Max(leftSum, rightSum) + root.data;
        }

        if (root.left != null)
            return leftSum + root.data;

        return rightSum + root.data;
    }

    static int maxPathSum(Node root)
    {
        if (root == null)
            return -1;

        int res = int.MinValue;
        maxPathSumUtil(root, ref res);

        return res == int.MinValue ? -1 : res;
    }

    static void Main()
    {
        Node root = new Node(3);
        root.left = new Node(4);
        root.right = new Node(5);
        root.left.left = new Node(-10);
        root.left.right = new Node(4);

        Console.WriteLine(maxPathSum(root));
    }
}
JavaScript
// Returns the maximum root-to-leaf path sum.
function maxPathSumUtil(root, res) {
    if (root == null)
        return 0;

    // Leaf node
    if (!root.left && !root.right)
        return root.key;

    // Recur for left and right subtrees
    let ls = maxPathSumUtil(root.left, res);
    let rs = maxPathSumUtil(root.right, res);

    // If both children exist, this node can connect two leaves
    if (root.left && root.right) {
        res[0] = Math.max(res[0], ls + rs + root.key);
        return Math.max(ls, rs) + root.key;
    }

    // Return the path through the existing child
    if (root.left)
        return ls + root.key;

    return rs + root.key;
}

function maxPathSum(root) {
    if (root == null)
        return -1;

    let res = [Number.MIN_SAFE_INTEGER];

    maxPathSumUtil(root, res);

    // No path exists between two leaf nodes.
    return res[0] === Number.MIN_SAFE_INTEGER ? -1 : res[0];
}

// Driver code
function Node(x) {
    this.key = x;
    this.left = null;
    this.right = null;
}

let root = new Node(3);
root.left = new Node(4);
root.right = new Node(5);
root.left.left = new Node(-10);
root.left.right = new Node(4);

console.log(maxPathSum(root));

Output
16
Comment