Definition
- 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_VALUEso 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.
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));
}
}
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.
// 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).
// 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
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.
---