Max Path Sum Between Two Leaves

Last Updated : 3 Sep, 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, 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] Find Path Between 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. For each pair, find their paths from the root and identify their Lowest Common Ancestor (LCA). The path between the two leaves passes through this LCA, so calculate its sum and keep track of the maximum.

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 = NULL;
    }
};

bool findPath(Node *root, Node *target, vector<Node*> &path) {
    if (root == NULL)
        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 == NULL)
        return;

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

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

int maxPathSum(Node *root) {
    if (root == NULL)
        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;

static 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 with Root-to-Leaf Path Sum - 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 = NULL;
    }
};

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 && 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 == NULL)
        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
27
Comment