how to find maximum path sum in a binary tree?

Link:http://www.geeksforgeeks.org/find-maximum-path-sum-in-a-binary-tree/
Unable to understand the logic could anyone explain it in detail?

-15
/
5 6
/ \ /
-8 1 3 9
/ \
2 6 0
/
4 -1
/
10

The maximum sum path may or may not go through root. For example, in the following binary tree, the maximum sum is 27(3 + 6 + 9 + 0 – 1 + 10). Expected time complexity is O(n).

Algorithm :

1 .We need sum for left and right binary sub tree.

2. we need to maintain current sum including that node.

3. compare current sum with previously obtained result and mark result with respect to it.

4. return maximum of Left or Right subTree + Current Node’s value.

To understand logic see how Sum for every node

for node = -8 Sum is = 0 , ls = 2 rs = 6

for node = 5 Sum is = 4 , ls = -2 rs = 1

for leaf = -1 Sum is = 4

for node = 0 Sum is = 13 , ls = 4 rs = 9

for leaf = 9 Sum is = 13

for node = 6 Sum is = 27 , ls = 3 rs = 18

for node = -15 Sum is = 27 , ls = 6 rs = 24

Max pathSum of the given binary tree is 27

So Now we can understand that.

  1. Recursive call to left and right subtree.

  2. to hold current sum.

    currentSum = leftSum + rightSum + root->value;

  3. To store result we need to pass it with reference, so that in each recursion it stays constant.

  4. return Maximum(leftSum, rightSum) + root->value.

    int maxPathSumUtil(struct Node *root, int &result) {
    if (root==NULL) return 0;
    //Step1
    int lLPSum = maxPathSumUtil(root->left, result);
    int rLPSum = maxPathSumUtil(root->right, result);
    //Step2
    int curr_sum = lLPSum + rLPSum + root->data;

          //Step3
     if (result < curr_sum) result = curr_sum;           
        
          //Step4     
     return max(lLPSum, rLPSum)+root->data;
    

    }

    int maxPathSum(struct Node *root) {
    int res = 0;
    maxPathSumUtil(root, result);
    cout<< result;
    }


    @beginner_1111 if you still facing problem you can ask me.

    [1]: https://i0.wp.com/www.gohired.in/wp-content/uploads/2015/05/binarytreemaximumpathsum.png?w=953

@codex0196, we can also use HashMap for caching for our DP.

For each node there can be four ways that the max path goes through the node:

  • Node only
  • Max path through Left Child + Node
  • Max path through Right Child + Node
  • Max path through Left Child + Node + Max path through Right Child

We can compute this for every node and store in a map.
Then we can traverse all values of hashmap and get the maximum one.

    public class Solution {
    
    // Each node stores the max value you can get when including that node as root
    HashMap<TreeNode, Integer> dp ;
    
    /**
     * Return max path including that node and saves it so hashMap 
     */
    private int calculate(TreeNode a) {
        if( a == null ) return -999999 ;
        if( a.left == null && a.right == null ) {
            if( !dp.containsKey(a) ) dp.put( a, a.val );
            return a.val;
            
        }
        if( dp.containsKey(a) ) return dp.get(a);
        int leftSum = calculate( a.left );
        int rightSum = calculate( a.right );
        int ans = Math.max( a.val, Math.max( leftSum + a.val, 
                    Math.max( rightSum + a.val, leftSum + rightSum + a.val )));
        dp.put( a, ans );
        return ans;
        
    }
    
    public int maxPathSum(TreeNode A) {
        dp = new HashMap<TreeNode, Integer>();
        int ans = calculate(A);
        
        Iterator<Map.Entry<TreeNode, Integer>> it = dp.entrySet().iterator();
        while(it.hasNext()) {
            int val = it.next().getValue();
            ans = Math.max(ans, val);
        }
        return ans;
    } 
  }

There seems to be an error in this approach. Can’t find that out.

The approach is not right because it adds the nodes maximum value instead of path value. A simple solution without dp which also does not work should make you understand why this solution does not work

 public class Solution {
    
    // Each node stores the max value you can get when including that node as root
   // HashMap<TreeNode, Integer> dp ;
    
    /**
     * Return max path including that node and saves it so hashMap 
     */
     
     int ans=Integer.MIN_VALUE;
     int countRecursion=0;
    private int calculate(TreeNode a) {
        if( a == null ) return -999999 ;
        if( a.left == null && a.right == null ) {
         //   if( !dp.containsKey(a) ) dp.put( a, a.val );
            return a.val;
            
        }
        //if( dp.containsKey(a) ) return dp.get(a);
        int leftSum = calculate( a.left );
        int rightSum = calculate( a.right );
        int ans = Math.max( a.val, Math.max( leftSum + a.val, 
                    Math.max( rightSum + a.val, leftSum + rightSum + a.val )));
        //dp.put( a, ans );
        return ans;
        
    }
    
    public int maxPathSum(TreeNode A) {
       // dp = new HashMap<TreeNode, Integer>();
        
        
        countRecursion++;
        
        int currentAns=calculate(A);
        ans = Math.max(ans,currentAns);
        
        System.out.println("when A is "+A.val+"call "+countRecursion+"currentAns is "+currentAns);
        
        if(A.left!=null)
           ans= maxPathSum(A.left);
        if(A.right!=null)
           ans= maxPathSum(A.right);
        
        
        
       
       // System.out.println(dp);
        return ans;
    } 
  }

We need to find out a way to not include the node’s max value. Instead we need to add to the path

Fixed the solution. I have not taken the sum(left+node+right) if the node is not root by taking a boolean variable

 public class Solution {
    
    // Each node stores the max value you can get when including that node as root
   // HashMap<TreeNode, Integer> dp ;
    
    /**
     * Return max path including that node and saves it so hashMap 
     */
     
     int ans=Integer.MIN_VALUE;
     int countRecursion=0;
    private int calculate(TreeNode a, boolean isRoot) {
        if( a == null ) return -999999 ;
        if( a.left == null && a.right == null ) {
         //   if( !dp.containsKey(a) ) dp.put( a, a.val );
            return a.val;
            
        }
        //if( dp.containsKey(a) ) return dp.get(a);
        
        
        int ans=0;
        int leftSum = calculate( a.left,false );
        int rightSum = calculate( a.right,false );
        
        if(isRoot)
          ans = Math.max( a.val, Math.max( leftSum + a.val, 
                    Math.max( rightSum + a.val, leftSum + rightSum + a.val )));
        else
             ans = Math.max( a.val, Math.max( leftSum + a.val, rightSum + a.val));
        //dp.put( a, ans );
        return ans;
        
    }
    
    public int maxPathSum(TreeNode A) {
       // dp = new HashMap<TreeNode, Integer>();
        
        
        countRecursion++;
        
        int currentAns=calculate(A,true);
        ans = Math.max(ans,currentAns);
        
        System.out.println("when A is "+A.val+"call "+countRecursion+"currentAns is "+currentAns);
        
        if(A.left!=null)
           ans= maxPathSum(A.left);
        if(A.right!=null)
           ans= maxPathSum(A.right);
        
        
        
       
       // System.out.println(dp);
        return ans;
    } 
  }