LeetCode 124 - Binary Tree Maximum Path Sum


Given a non-empty binary tree, find the maximum path sum.
For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.
Example 1:
Input: [1,2,3]

       1
      / \
     2   3

Output: 6
Example 2:
Input: [-10,9,20,null,null,15,7]

   -10
   / \
  9  20
    /  \
   15   7

Output: 42

PostOrder traverse the whole tree. For each  node calculate Max(root, root+leftSide, root+rightSide, leftSide+root+rightSide ), update max[0] (which is used to store max value), then return Max (root+leftSide, root+rightSide, root)
https://leetcode.com/problems/binary-tree-maximum-path-sum/discuss/39775/Accepted-short-solution-in-Java
The basic idea is to traversal every nodes as the top of sub tree and calculate left max and right max individually, then keep update max. The most elegant point is that you did both in one method, implemented it by not only return but also keeping updating max as a field.

  • A recursive method maxPathDown(TreeNode node) (1) computes the maximum path sum with highest node is the input node, update maximum if necessary (2) returns the maximum sum of the path that can be extended to input node's parent.

maxValue = Math.max(maxValue, left + right + node.val);
return Math.max(left, right) + node.val;
maxValue is the value which recording whether this current root is the final root, so we use left + right + node.val. But to the upper layer(after return statement), we cannot choose both left and right brunches, so we need to select the larger one, so we usemax(left, right) + node.val to prune the lower brunch.
public class Solution {
    int maxValue;
    
    public int maxPathSum(TreeNode root) {
        maxValue = Integer.MIN_VALUE;
        maxPathDown(root);
        return maxValue;
    }
    
    private int maxPathDown(TreeNode node) {
        if (node == null) return 0;
        int left = Math.max(0, maxPathDown(node.left));
        int right = Math.max(0, maxPathDown(node.right));
        maxValue = Math.max(maxValue, left + right + node.val);
        return Math.max(left, right) + node.val;
    }
}
My approach to avoid global variable
public int maxPathSum(TreeNode root) {
    int[] max = new int[1];
    max[0] = Integer.MIN_VALUE;
    maxPathSum(max, root);
    return max[0];
}
private int maxPathSum(int[] max, TreeNode root){
    if(root == null)
        return 0;
    int leftMax =  Math.max(0, maxPathSum(max, root.left));
    int rightMax = Math.max(0, maxPathSum(max, root.right));
    max[0] = Math.max(max[0],  root.val+leftMax+rightMax);
    return root.val+Math.max(leftMax,rightMax);
}
https://discuss.leetcode.com/topic/17823/elegant-java-solution
    int max = Integer.MIN_VALUE;
    
    public int maxPathSum(TreeNode root) {
        helper(root);
        return max;
    }
    
    // helper returns the max branch 
    // plus current node's value
    int helper(TreeNode root) {
        if (root == null) return 0;
        
        int left = Math.max(helper(root.left), 0);
        int right = Math.max(helper(root.right), 0);
        
        max = Math.max(max, root.val + left + right);
        
        return root.val + Math.max(left, right);
    }
http://blog.csdn.net/fightforyourdream/article/details/16894069
For each node like following, there should be four ways existing for max path:
1. Node only (因为本题中的节点可能是负值!)
2. L-sub + Node
3. R-sub + Node
4. L-sub + Node + R-sub

Keep trace the four path and pick up the max one in the end.  

 public static int maxPathSum(TreeNode root) {
  int[] max = {Integer.MIN_VALUE};  // 因为Java里都是pass by value所以利用数组传!
        rec(root, max);
        return max[0];
    }
 public static int rec(TreeNode root, int[] max){
  if(root == null){
         return 0;
        }
        int leftSubtreeMaxSum = rec(root.left, max);  // 左子树的最大和
        int rightSubtreeMaxSum = rec(root.right, max);  // 右子树的最大和
        int arch = leftSubtreeMaxSum + root.val + rightSubtreeMaxSum;  // 从左子树经过root到右子树的最大和
        
        // 表示通过root节点能走到root的parent的最大和,这个值作为返回对象返给调用父函数
        // 只有3中情况: 1 从左子树到root再到parent
        // 2 从右子树到root再到parent
        // 3 直接从root到parent
        // 注意arch那条路是不可能走到parent,因为那条路已经经过root了,除非折回来重复走!但这是不允许的
        int maxPathAcrossRootToParent = Math.max(root.val, Math.max(leftSubtreeMaxSum, rightSubtreeMaxSum)+root.val);
        
        // max[0] 保存在所有递归过程中的最大值,这时也要考虑arch可能最大
        max[0] = Math.max(max[0], Math.max(arch, maxPathAcrossRootToParent));
        return maxPathAcrossRootToParent;
 }
http://www.jiuzhang.com/solutions/binary-tree-maximum-path-sum/
http://ying.ninja/?p=964
    private class ResultType {
        int singlePath, maxPath;
        ResultType(int singlePath, int maxPath) {
            this.singlePath = singlePath;
            this.maxPath = maxPath;
        }
    }

    private ResultType helper(TreeNode root) {
        if (root == null) {
            return new ResultType(Integer.MIN_VALUE, Integer.MIN_VALUE);
        }
        // Divide
        ResultType left = helper(root.left);
        ResultType right = helper(root.right);

        // Conquer
        int singlePath =
            Math.max(0, Math.max(left.singlePath, right.singlePath)) + root.val;

        int maxPath = Math.max(left.maxPath, right.maxPath);
        maxPath = Math.max(maxPath,
                           Math.max(left.singlePath, 0) + 
                           Math.max(right.singlePath, 0) + root.val);

        return new ResultType(singlePath, maxPath);
    }
X. Pruning
https://leetcode.com/discuss/43797/elegant-java-solution
the key point is replacing the negative max value and null nodes value with 0, thus there would no negative value in any binary tree, and we need not care about any single node.
public class Solution { int max = Integer.MIN_VALUE; public int maxPathSum(TreeNode root) { helper(root); return max; } // helper returns the max branch // plus current node's value int helper(TreeNode root) { if (root == null) return 0; int left = Math.max(helper(root.left), 0); int right = Math.max(helper(root.right), 0); max = Math.max(max, root.val + left + right); return root.val + Math.max(left, right); } }

http://www.chenguanghe.com/binary-tree-maximum-path-sum/
遍历所有node, 如果当前的path sum小于0, 那么是对sum没帮助的, 只关心大于0的. 然后找到最大就行了
int max = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        if(root == null)
            return 0;
        helper(root);
        return max;
    }
    
    public int helper(TreeNode root) {
        if (root == null) return 0;
        int left = Math.max(helper(root.left), 0);
        int right = Math.max(helper(root.right), 0);
        max = Math.max(max, root.val + left + right);
        return root.val + Math.max(left, right);
    }

Recursive Version:
[leetcode] Binary Tree Maximum Path Sum |树中任意两点间最大path sum
arch代表穿过当前节点的路径(左边一支儿+自己节点+右边一支儿)。
注意树的节点可以是负数,所以arch不一定是最长的。
每次return以root(当前节点)开头最大的单只path sum。
后来发现,没有分清最大值和递归函数的返回值。在求值函数里面不能把计算出来的最大值作为返回值返回回去,否则会有问题。
全局最优解 和局部最优解
public int maxPathSum(TreeNode root) {
    int[] res = new int[1];
    res[0] = Integer.MIN_VALUE;
    maxPath(root, res);
    return res[0];
}
private int maxPath(TreeNode root, int[] res) {
    if (root == null)
        return 0;
    int left = maxPath(root.left, res);//左边一支儿(不算自己)
    int right = maxPath(root.right, res);
    int arch = left + right + root.val; //穿过自己
    int single = Math.max(root.val, Math.max(left, right) + root.val);(算上自己)
    res[0] = Math.max(res[0], Math.max(arch, single));//update结果
    return single;
}
http://hehejun.blogspot.com/2015/01/leetcodebinary-tree-maximum-path-sum.html
Use instance field.
注意path可以在tree里的任意节点开始和结束,我们需要用bottom-up的方法,在每一个节点,先递归找到左子树和右子树的一直朝上走的maximum path sum,然后两边与自己的值的和若比现在的max sum大,更新sum。然后从左子树和右子树的最大值挑一个大的与自己的和return上去,注意如果小于等于0的话就直接return0,因为会使得值变得更小。
public class Solution {
 
    private int sum = Integer.MIN_VALUE;
 
    public int maxPathSum(TreeNode root) {
        findMaxSum(root);
        return sum;
    }
 
    private int findMaxSum(TreeNode node) {
        if (node == null)
            return 0;
        int left = findMaxSum(node.left);
        int right = findMaxSum(node.right);
        int currSum = left + node.val + right;
        if (currSum > sum)
            sum = currSum;
        int retPath = left >= right? left + node.val: right + node.val;
        return retPath > 0? retPath: 0;
    }
}
http://www.programcreek.com/2013/02/leetcode-binary-tree-maximum-path-sum-java/
1) Recursively solve this problem
2) Get largest left sum and right sum
2) Compare to the stored maximum
public int maxPathSum(TreeNode root) {
 int max[] = new int[1]; 
 max[0] = Integer.MIN_VALUE;
 calculateSum(root, max);
 return max[0];
}
 
public int calculateSum(TreeNode root, int[] max) { //use int[]
 if (root == null)
  return 0;
 
 int left = calculateSum(root.left, max);
 int right = calculateSum(root.right, max);
 
 int current = Math.max(root.val, Math.max(root.val + left, root.val + right));
 
 max[0] = Math.max(max[0], Math.max(current, left + root.val + right));
 
 return current;
}
http://java.freesion.com/article/5069670101/
  1.     int fun(TreeNode *root, int &max) //递归计算单向路径最大和  
  2.     {  
  3.         if(root == NULL)  
  4.             return 0;  
  5.           
  6.         int left = fun(root->left, max);  
  7.         if(left < 0) //如果为负就剪掉  
  8.             left = 0;  
  9.         int right = fun(root->right, max);  
  10.         if(right < 0) //如果为负就剪掉  
  11.             right = 0;  
  12.               
  13.         // 在递归过程中考察以root为中心的双向路径的和  
  14.         if(left + right + root->val > max)  
  15.             max = left + right + root->val;  
  16.           
  17.         if(left > right)  
  18.             return left + root->val;  
  19.         else  
  20.             return right + root->val;  
  21.           
  22.     } 
http://www.geeksforgeeks.org/find-maximum-path-sum-in-a-binary-tree/
// An object of Res is passed around so that the
// same value can be used by multiple recursive calls.
class Res {
    public int val;
}
class BinaryTree {
    // Root of the Binary Tree
    Node root;
    // This function returns overall maximum path sum in 'res'
    // And returns max path sum going through root.
    int findMaxUtil(Node node, Res res)
    {
        // Base Case
        if (node == null)
            return 0;
        // l and r store maximum path sum going through left and
        // right child of root respectively
        int l = findMaxUtil(node.left, res);
        int r = findMaxUtil(node.right, res);
        // Max path for parent call of root. This path must
        // include at-most one child of root
        int max_single = Math.max(Math.max(l, r) + node.data,
                                  node.data);
        // Max Top represents the sum when the Node under
        // consideration is the root of the maxsum path and no
        // ancestors of root are there in max sum path
        int max_top = Math.max(max_single, l + r + node.data);
        // Store the Maximum Result.
        res.val = Math.max(res.val, max_top);
        return max_single;
    }
    int findMaxSum() {
        return findMaxSum(root);
    }
    // Returns maximum path sum in tree with given root
    int findMaxSum(Node node) {
        // Initialize result
        // int res2 = Integer.MIN_VALUE;
        Res res = new Res();
        res.val = Integer.MIN_VALUE;
        // Compute and return result
        findMaxUtil(node, res);
        return res.val;
    }
Also refer to http://blog.csdn.net/fightforyourdream/article/details/16894069
https://gist.github.com/benjaminwu7/4700454#file-leetcode-binary-tree-maximum-path-sum-java

[LintCode] 475 Binary Tree Maximum Path Sum II
https://xuezhashuati.blogspot.com/2017/04/lintcode-475-binary-tree-maximum-path.html
Given a binary tree, find the maximum path sum from root.
The path may end at any node in the tree and contain at least one node in it.

Example
Given the below binary tree:

  1
 / \
2   3
return 4. (1->3)



思路
分治法。
以当前点开始的maxSum,取决于:
1:以当前点的左儿子为开始的maxSum是否大于0
2:以当前点的右儿子为开始的maxSum是否大于0

如果两者都小于0,那么以当前点开始的maxSum就是当前点的值。
    public int maxPathSum2(TreeNode root) {
        // Write your code here
        
        if (root == null) {
            return 0;
        }
        
        int left = maxPathSum2(root.left);
        int right = maxPathSum2(root.right);
        
        if (Math.max(left, right) < 0) {
            return root.val;
        }
        
        return Math.max(left, right) + root.val;
    }

1. 我没问清每个Node是不不是都是正数,结果按照正数做的,然后⾯面试官
给了了个全是负数的例例⼦子,我就懵了了没想出来怎么解。以前做过但是好久没
看已经忘了了………后来补了了⼀一个限制条件简化题⽬目,就是如果node是负
数,可以跳过不不加这个node,然后应该是做出来了了
2. follow up是max subtree sum 和 sub-structure的sum
3. follow up是打印出path

https://github.com/mintycc/OnlineJudge-Solutions/blob/master/Leetcode/124_Binary_Tree_Maximum_Path_Sum.java
Facebook惜败
https://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=454205
recursive function返回当前root下最大sum的path,然后用一个global max_sum_path去存最终答案。

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts