Binary Tree Maximum Path Sum

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.

Given the root of a binary tree, return the maximum path sum of any path.

Example 1:

Input: root = [1,2,3]
Output: 6
Explanation: The optimal path is 2 -> 1 -> 3 with a path sum of 2 + 1 + 3 = 6.

Example 2:

Input: root = [-10,9,20,null,null,15,7]
Output: 42
Explanation: The optimal path is 15 -> 20 -> 7 with a path sum of 15 + 20 + 7 = 42.

Constraints:

  • The number of nodes in the tree is in the range [1, 3 * 104].
  • -1000 <= Node.val <= 1000

Recursion

First of all, let’s simplify the problem and implement a function max_gain(node) which takes a node as an argument and computes a maximum contribution that this node and one/zero of its subtrees could add.

In other words, it’s a maximum gain one could have including the node (and maybe one of its subtrees) into the path.

Hence if one would know for sure that the max path contains root, the problem would be solved as max_gain(root). Unfortunately, the max path does not need to go through the root, and here is an example of such a tree.

That means one needs to modify the above function and to check at each step what is better: to continue the current path or to start a new path with the current node as the highest node in this new path.

Algorithm

Now everything is ready to write down an algorithm.

  • Initiate max_sum as the smallest possible integer and call max_gain(node = root).
  • Implement max_gain(node) with a check to continue the old path/to start a new path:
  • Base case: if the node is null, the max gain is 0.
  • Call max_gain recursively for the node children to computing max gain from the left and right subtrees : left_gain = max(max_gain(node.left), 0) and
    right_gain = max(max_gain(node.right), 0).
  • Now check to continue the old path or to start a new path. To start a new path would cost price_newpath = node.val + left_gain + right_gain. Update max_sum if it's better to start a new path.
  • For the recursion return the max gain the node and one/zero of its subtrees could add to the current path : node.val + max(left_gain, right_gain).

Implementation

Complexity Analysis

  • Time complexity: O(N), where N is a number of nodes, since we visit each node not more than 2 times.
  • Space complexity: O(H), where H is a tree height, to keep the recursion stack.

Full Stack Programmer, love to solve problem’s during free time.