Back to Beginner: I/O, Arithmetic, Loops
Q15Question 15 of 30

Path with Maximum Sum (Maximum Sum of Any Path Between Two Nodes)

Key Concepts
  • Each node plays two roles: it returns its best single-branch gain upward, but updates the global maximum with the bent two-branch path.
  • Clamp each child's contribution at zero with Math.max(0, childGain) so harmful branches are ignored.
  • The global maximum must be initialized to the smallest possible value (Integer.MIN_VALUE), not zero, because all nodes may be negative.
  • The asymmetry between what is returned (single branch) and what updates the global (bent path) is the classic bug source.
  • Time is O(n) with a single post-order traversal; space is O(h) for the recursion stack.
  • For monetary values, use BigDecimal and clamp at BigDecimal.ZERO to skip loss-making branches.

Definition

Return the best clamped downward branch to the parent, but update the global best with node value plus both clamped branches.
  • Post-order traversal – process children first, then the current node, so child gains are known before the node decides.
  • Single branch return – to the parent, offer node.value + max(leftGain, rightGain), the best straight extension.
  • Bent path update – update the global max with node.value + leftGain + rightGain, the best path bending through this node.
  • Zero clamp – Math.max(0, childGain) ignores branches that would lower the sum.
  • Initialization – seed globalMax = Integer.MIN_VALUE so a tree of all negatives returns the least-negative single node.

At National Bank of India, each desk in a tree contributes a profit or a loss. Strategy wants the single most profitable connected stretch of desks, which can run up one branch and down another through a middle desk. If a sub-branch would only drag the total down, it is simply ignored.

Understanding the Concepts

What is the problem?

Find the maximum sum over any connected path in a binary tree. A path is a sequence of connected nodes, and it need not pass through the root or touch a leaf. Node values may be negative.

How does the post-order approach work?

  • Each node plays two roles:
  • To its parent it offers a straight downward extension: node.value + max(leftGain, rightGain).
  • Internally, it considers a path that bends through itself using both children: node.value + leftGain + rightGain.

The bent path cannot be extended further upward (it already uses both branches), so it only updates the global max, not the return value.

JAVA
package com.bank.service;

public class MaxPathSumFinder {

    static class TreeNode {
        int val;
        TreeNode left, right;
        TreeNode(int val) { this.val = val; }
    }

    private static int globalMax;

    public static int maxPathSum(TreeNode root) {
        globalMax = Integer.MIN_VALUE;
        dfs(root);
        return globalMax;
    }

    private static int dfs(TreeNode node) {
        if (node == null) return 0;

        int leftGain = Math.max(0, dfs(node.left));   // clamp at 0
        int rightGain = Math.max(0, dfs(node.right));  // clamp at 0

        // Bent path through this node
        int bentPath = node.val + leftGain + rightGain;
        globalMax = Math.max(globalMax, bentPath);

        // Return single branch to parent
        return node.val + Math.max(leftGain, rightGain);
    }

    public static void main(String[] args) {
        // Profit/loss desks at National Bank of India
        TreeNode root = new TreeNode(10);
        root.left = new TreeNode(2);
        root.right = new TreeNode(10);
        root.left.left = new TreeNode(20);
        root.left.right = new TreeNode(1);
        root.right.right = new TreeNode(-25);
        root.right.right.left = new TreeNode(3);
        root.right.right.right = new TreeNode(4);

        System.out.println("Maximum path sum: " + maxPathSum(root));
    }
}
TEXT
Maximum path sum: 42

The best path is 20 - 2 - 10 - 10 = 42 (going up from 20 through 2 to root 10, then down to right child 10).

Why clamp at zero?

If extending into a child would lower the sum, the optimal path simply stops at the current node. Math.max(0, childGain) handles this: a negative gain becomes zero, meaning that branch is not used.

JAVA
// Without clamping: path forced to include losing branches
int leftGain = dfs(node.left); // might be -50, dragging sum down

// With clamping: losing branches ignored
int leftGain = Math.max(0, dfs(node.left)); // -50 becomes 0

Why initialize globalMax to Integer.MIN_VALUE?

A tree of all-negative values has a maximum path equal to the single least-negative node. If you seed globalMax at zero, you would wrongly return zero even though zero is not a valid path sum (no such path exists).

JAVA
// Wrong: seed at 0
int globalMax = 0; // returns 0 for tree [-3, -5, -1]

// Correct: seed at MIN_VALUE
int globalMax = Integer.MIN_VALUE; // returns -1 for tree [-3, -5, -1]

What is the asymmetry between return and update?

This is the most common bug. The return value to the parent is a single branch (can only extend one way). The global update uses both branches (bends through the node). Confusing the two causes wrong answers.

| | Return to parent | Global update |
|---|---|---|
| Formula | node + max(left, right) | node + left + right |
| Can extend? | Yes, parent adds more | No, already uses both branches |
| Purpose | offer best extension | record best complete path |

What are edge cases?

  • Single node: the answer is that node's value.
  • All negative: the answer is the least-negative single node.
  • Perfect tree of positive values: the best path goes through the root using both subtrees.

What should a senior engineer know?

For monetary values in a profit-and-loss tree at National Bank of India, use BigDecimal to avoid overflow and clamp losses at BigDecimal.ZERO. The global max is seeded at a very large negative BigDecimal. The pattern generalizes to any tree problem where you need the best connected substructure.

What are common interview follow-up questions?

  • How would you return the actual path, not just the sum?
  • What if the path must include the root?
  • Can you solve this iteratively with an explicit stack?

Visual Overview

DIAGRAM
         10
        /  \
       2    10
      / \     \
    20   1    -25
              /  \
             3    4

  DFS returns:
    20 → gain 20    1 → gain 1
    2 + max(20,1) = 22 (return to parent)
    2 + 20 + 1 = 23 (bent, update global)

    3 → gain 3     4 → gain 4
    -25 + max(3,4) = -21 → clamped to 0 (return)
    -25 + 3 + 4 = -18 (bent, update global)

    10 (right) + max(0, 0) = 10 (return)
    10 + 0 + 0 = 10 (bent)

    10 (root) + max(22, 10) = 32 (return)
    10 + 22 + 10 = 42 (bent) ← GLOBAL MAX

Key Takeaway

Path with Maximum Sum finds the maximum sum over any connected path in a binary tree, where the path can bend through a node using both children. The solution is a post-order traversal where each node returns its best single-branch extension to the parent but updates a global maximum with the bent two-branch path.

The decisive detail is clamping each child's gain at zero. If extending into a child would lower the total, the optimal path stops at the current node. The other critical detail is seeding the global maximum at Integer.MIN_VALUE, not zero, because a tree of all-negative nodes must return its least-negative single node.

The classic bug is confusing what is returned (single branch) with what updates the global (bent path). The return is node + max(left, right) because it can be extended by the parent. The update is node + left + right because it already uses both branches and cannot be extended further.

In a banking project at National Bank of India, each desk in a profit-and-loss tree contributed a gain or a loss, and strategy wanted the single most profitable connected run. Loss-making sub-branches were clamped to zero so they were ignored, and the global best was updated with the bent two-branch path.

Remember one sentence: return the best single branch to the parent, but update the global with node plus both clamped branches.

---

Share
Use ← → arrow keys to navigate