Maximum Path Sum in Binary Tree in DSA Javascript - Time & Space Complexity
We want to understand how the time needed to find the maximum path sum in a binary tree grows as the tree gets bigger.
Specifically, how does the number of steps change when the number of nodes increases?
Analyze the time complexity of the following code snippet.
function maxPathSum(root) {
let maxSum = -Infinity;
function dfs(node) {
if (!node) return 0;
const left = Math.max(dfs(node.left), 0);
const right = Math.max(dfs(node.right), 0);
maxSum = Math.max(maxSum, node.val + left + right);
return node.val + Math.max(left, right);
}
dfs(root);
return maxSum;
}
This code finds the maximum sum of any path in a binary tree, where a path can start and end at any nodes.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive depth-first search (dfs) visits each node once.
- How many times: Each node is visited exactly one time during recursion.
As the number of nodes grows, the function visits each node once, so the total steps grow roughly in direct proportion to the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits |
| 100 | About 100 visits |
| 1000 | About 1000 visits |
Pattern observation: The number of operations grows linearly with the number of nodes.
Time Complexity: O(n)
This means the time to find the maximum path sum grows in a straight line with the number of nodes in the tree.
[X] Wrong: "The recursion visits nodes multiple times, so the time is more than linear."
[OK] Correct: Each node is visited once, and results are combined on the way back, so no repeated work happens.
Understanding this time complexity helps you explain how efficient your tree algorithms are, a key skill in many coding challenges and interviews.
"What if the tree was very unbalanced, like a linked list? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem definition
The problem asks for the maximum sum of node values along any path in the binary tree. A path can start and end at any nodes, but must be connected.Step 2: Differentiate from other path problems
This is not about longest path length or total sum of all nodes, but the maximum sum of values on any path.Final Answer:
The highest sum of values along any path between two nodes in the tree -> Option CQuick Check:
Maximum path sum = highest sum path [OK]
- Confusing maximum path sum with longest path length
- Thinking path must start at root
- Summing all nodes instead of a path
Solution
Step 1: Consider the meaning of base case for null node
When the node is null, the maximum gain from this subtree is 0 (choose not to extend path here).Step 2: Why not others?
-Infinity works only with Math.max(0, result) but 0 is standard and cleaner. Returning 0 allows proper clamping in parent. null or 1 cause type/math errors.Final Answer:
0 -> Option DQuick Check:
Base case for null = 0 [OK]
- Returning -Infinity without Math.max(0, ยท)
- Returning null causing type errors
- Returning positive values skewing max
class TreeNode {
constructor(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
function maxPathSum(root) {
let maxSum = -Infinity;
function dfs(node) {
if (!node) return 0;
let left = Math.max(dfs(node.left), 0);
let right = Math.max(dfs(node.right), 0);
maxSum = Math.max(maxSum, node.val + left + right);
return node.val + Math.max(left, right);
}
dfs(root);
return maxSum;
}
const root = new TreeNode(-10, new TreeNode(9), new TreeNode(20, new TreeNode(15), new TreeNode(7)));
console.log(maxPathSum(root));Solution
Step 1: Trace dfs on left subtree
Left child 9: left=0, right=0, maxSum = 9, returns 9.Step 2: Trace dfs on right subtree
dfs(15)=15 updates maxSum=15; dfs(7)=7 keeps 15; at 20: left=15, right=7, maxSum = max(15, 20+15+7=42)=42, returns 20+15=35.Step 3: Calculate root node max sum
Root: left=9, right=35, path sum -10+9+35=34 <42, maxSum remains 42.Final Answer:
42 -> Option AQuick Check:
Max path sum = 42 [OK]
- Not ignoring negative sums by using Math.max with 0
- Adding left and right children incorrectly
- Confusing return value with maxSum update
function maxPathSum(root) {
let maxSum = -Infinity;
function dfs(node) {
if (!node) return -Infinity;
let left = dfs(node.left);
let right = dfs(node.right);
maxSum = Math.max(maxSum, node.val + left + right);
return node.val + Math.max(left, right);
}
dfs(root);
return maxSum;
}Solution
Step 1: Analyze base case and recursive calls
Returning -Infinity for null nodes causes left and right to be -Infinity, which breaks addition and max calculations.Step 2: Fix by ignoring negative sums
Use Math.max(dfs(node.left), 0) and Math.max(dfs(node.right), 0) to ignore negative paths and avoid incorrect sums.Final Answer:
Add check to ignore negative sums with Math.max(left, 0) -> Option AQuick Check:
Ignore negative sums with Math.max(..., 0) [OK]
- Returning -Infinity breaks addition
- Not ignoring negative sums from children
- Changing maxSum initialization wrongly
Solution
Step 1: Understand all-negative case
The max path sum is the highest (least negative) single node value. Paths must include at least one node.Step 2: Key modification
Tracking the maximum single node value separately ensures that if all child sums are negative, the algorithm still returns the maximum node value. Using Math.max(0, dfs(child)) ignores negative child sums but can miss the max single node if all are negative.Final Answer:
Track the maximum single node value separately and compare with path sums -> Option BQuick Check:
Separate max node tracking handles all-negative correctly [OK]
- Allowing empty path return 0 (invalid)
- Not tracking max node separately (misses max negative node)
- Not ignoring negative child sums (misses single nodes)
Ready to prove it?
Pass the test and this pattern moves unknown
