Open In App

Find the maximum path sum between two leaves of a binary tree using JavaScript

Last Updated : 21 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given the root of a binary tree, return the maximum path sum of any non-empty path. A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root. The path sum of a path is the sum of the node's values in the path.

undefined-(3)
Maximum path sum is 42.

Using Postorder Traversal

In this approach we traverse each node of the tree using inorder, preorder, or postorder traversal. For each node, consider it as the root and recursively find the maximum left path sum and maximum right path sum. Update the final answer with the maximum value found.

Example: To demonstrate finding the maximum path sum between to leaves of a binary tree using Javascript.

JavaScript
class TreeNode {
    constructor(val) {
        this.val = val;
        this.left = this.right = null;
    }
}

// Helper function to find the maximum 
// path sum from the given node to any leaf
function PathSum(node) 
{
    if (node === null) return 0;
    if (node.left === null && node.right === null)
        return node.val;
    // Leaf node

    const leftSum = node
        .left ? PathSum(node.left) : -Infinity;
    const rightSum = node
        .right ? PathSum(node.right) : -Infinity;

    return node
        .val + Math
            .max(leftSum, rightSum);
}

// Function to find the maximum path sum between 
// two leaf nodes considering the given node as root
function maxPathSumNode(node)
{
    if (node === null) return -Infinity;
    if (node.left === null || node.right === null)
        return -Infinity;

    const leftSum = PathSum(node.left);
    const rightSum = PathSum(node.right);

    return leftSum + rightSum + node.val;
}

// Function to traverse the tree
//  and update the maximum path sum
function traverseTree(node, maxSum) {
    if (node === null) return;

    const currentMax = maxPathSumNode(node);
    if (currentMax > maxSum.value) maxSum.
    value = currentMax;

    traverseTree(node.left, maxSum);
    traverseTree(node.right, maxSum);
}

// The main function to return
//  the maximum sum between two leaves
function maxSum(root) {
    let maxSum = { value: -Infinity };
    traverseTree(root, maxSum);
    return maxSum.value;
}

// Utility function to create a new tree node
function newNode(data) {
    return new TreeNode(data);
}

// Example usage
const root = newNode(-10);
root.left = newNode(9);
root.right = newNode(20);
root.right.left = newNode(15);
root.right.right = newNode(7);

console.log("Max path sum of the given binary tree is " + maxSum(root));

Time Complexity: O(N^2) in the worst case due to repeated subtree traversals.

Space Complexity: O(H), where H is the height of the tree (O(log N) for a balanced tree and O(N) for a skewed tree).

In this approach we start with the base case. If the current node is null, return 0. For each node, calculate the maximum path sum that includes that node. Recursively traverse the left and right subtrees to get their maximum path sums. Update the global maximum sum if a new maximum path sum is found. Return the maximum path sum including the current node to the parent.

Example: To demonstrate finding the maximum path sum between to leaves of a binary tree using Javascript.

JavaScript
class TreeNode {
    constructor(val = 0, left = null, right = null)
    {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

class Solution {
    maxPathSum(root) {
        let ans = [-Infinity];
        // Initialize with negative 
        // infinity for comparison

        function DFS(root)
        {
            if (root === null)
            {
                return 0;
            }
            let lmax = Math
                .max(0, DFS(root.left));
            let rmax = Math
                .max(0, DFS(root.right));

            // Update the overall 
            // maximum path sum
            ans[0] = Math
                .max(ans[0], root.val + lmax + rmax);

            // Return the maximum path sum
            // that starts from the current node
            return root
                .val + Math
                    .max(lmax, rmax);
        }

        // Call the DFS function
        //  on the root node
        DFS(root);

        // Return the final maximum path sum
        return ans[0] !== -Infinity ? ans[0] : 0;
        // If ans is still -Infinity, return 0
    }
}

// Example input
let root = new TreeNode(-10);
root.left = new TreeNode(9);
root.right = new TreeNode(20);
root.right.left = new TreeNode(15);
root.right.right = new TreeNode(7);

let solution = new Solution();
console.log(solution.maxPathSum(root));

Time Complexity: O(N)

Space Complexity: O(H), where H is the height of the tree (O(log N) for a balanced tree and O(N) for a skewed tree).

Using Dynamic Programming on Trees

This approach involves the use of dynamic programming (DP) to avoid redundant calculations. We maintain a DP table where each entry corresponds to the maximum path sum obtainable for the subtree rooted at each node. By caching the results of the subproblems, we can reduce the time complexity of the solution.

Steps:

  1. For each node, calculate the maximum path sum that can be obtained starting from that node (this can be considered as the subproblem).
  2. Use the results of the subproblems to calculate the maximum path sum that includes the node and its children.
  3. Update the global maximum path sum if a new maximum is found.

Example: Implementation of above discussed approach

JavaScript
class TreeNode {
    constructor(val) {
        this.val = val;
        this.left = this.right = null;
    }
}

class Solution {
    constructor() {
        this.dp = new Map(); // Map to store the DP results
    }

    maxPathSum(root) {
        let maxSum = { value: -Infinity };
        this.findMaxPath(root, maxSum);
        return maxSum.value;
    }

    findMaxPath(node, maxSum) {
        if (node === null) return 0;

        // Check if the result for this node is already calculated
        if (this.dp.has(node)) return this.dp.get(node);

        // Calculate the maximum path sum of left and right children
        let leftMax = Math.max(0, this.findMaxPath(node.left, maxSum));
        let rightMax = Math.max(0, this.findMaxPath(node.right, maxSum));

        // Update the global maximum path sum including this node
        let currentMax = node.val + leftMax + rightMax;
        maxSum.value = Math.max(maxSum.value, currentMax);

        // Store the result in the DP table and return the maximum path sum 
        // starting from this node to its parent
        let result = node.val + Math.max(leftMax, rightMax);
        this.dp.set(node, result);

        return result;
    }
}

// Example usage
let root = new TreeNode(-10);
root.left = new TreeNode(9);
root.right = new TreeNode(20);
root.right.left = new TreeNode(15);
root.right.right = new TreeNode(7);

let solution = new Solution();
console.log("Max path sum of the given binary tree is " + solution.maxPathSum(root));

Output
Max path sum of the given binary tree is 42

Next Article

Similar Reads