DP on Trees Maximum Path Sum in DSA Typescript - Time & Space Complexity
We want to understand how the time needed to find the maximum path sum in a tree grows as the tree gets bigger.
Specifically, how does the number of steps change when the tree has more nodes?
Analyze the time complexity of the following code snippet.
function maxPathSum(root: TreeNode | null): number {
let maxSum = -Infinity;
function dfs(node: TreeNode | null): number {
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 values along any path in a binary tree using a depth-first search.
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 the recursion.
As the number of nodes in the tree increases, the number of recursive calls grows linearly.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 recursive calls |
| 100 | About 100 recursive calls |
| 1000 | About 1000 recursive calls |
Pattern observation: The number of steps grows directly in proportion to the number of nodes.
Time Complexity: O(n)
This means the time to find the maximum path sum grows linearly with the number of nodes in the tree.
[X] Wrong: "Because the function calls itself twice per node, the time is O(2^n)."
[OK] Correct: Each node is visited only once because the recursion branches do not overlap; the calls form a tree structure with n nodes, so total calls are n, not exponential.
Understanding this linear time complexity helps you explain how efficient tree algorithms work and shows you can analyze recursive solutions clearly.
"What if the tree was very unbalanced and looked like a linked list? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem definition
The maximum path sum is about finding the path between any two nodes that yields the highest sum of node values.Step 2: Differentiate from other sums
It is not the sum of all nodes or just the max node value, but the max sum along a connected path.Final Answer:
The largest sum of node values along any path between two nodes in the tree -> Option BQuick Check:
Maximum path sum = max sum on any path [OK]
- Confusing maximum path sum with sum of all nodes
- Thinking it is just the max node value
- Assuming path must start at root
Solution
Step 1: Check parameter type
The function must accept a TreeNode or null to handle empty nodes.Step 2: Check return type
It should return a number representing the max path sum from that node.Final Answer:
function maxPathSum(node: TreeNode | null): number -> Option DQuick Check:
Correct parameter and return type [OK]
- Using wrong parameter type (e.g., number instead of TreeNode)
- Returning void instead of number
- Not allowing null for leaf children
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val = 0, left: TreeNode | null = null, right: TreeNode | null = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
function maxPathSum(root: TreeNode | null): number {
let maxSum = -Infinity;
function dfs(node: TreeNode | null): number {
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;
}
const tree = new TreeNode(1, new TreeNode(2), new TreeNode(3));
console.log(maxPathSum(tree));What is the output of this code?
Solution
Step 1: Trace DFS on tree nodes
For node 2 and 3, max path sums are 2 and 3 respectively. For root 1, left=2, right=3.Step 2: Calculate maxSum updates
maxSum updates to max(-Infinity, 1+2+3) = 6. Return value for root is 1 + max(2,3) = 4 but maxSum remains 6.Final Answer:
6 -> Option CQuick Check:
Sum of path 2->1->3 = 6 [OK]
- Returning max path from root only, ignoring subtrees
- Not using Math.max with 0 to ignore negative sums
- Confusing return value with maxSum global
function maxPathSum(root: TreeNode | null): number {
let maxSum = -Infinity;
function dfs(node: TreeNode | null): number {
if (!node) return 0;
const left = dfs(node.left);
const right = dfs(node.right);
maxSum = Math.max(maxSum, node.val + left + right);
return node.val + Math.max(left, right);
}
dfs(root);
return maxSum;
}What is the bug in this code?
Solution
Step 1: Analyze subtree sums usage
The code uses left and right sums directly without ignoring negative values.Step 2: Identify impact on maxSum
Negative sums can reduce maxSum, so we must use Math.max(dfs(...), 0) to ignore negatives.Final Answer:
It does not ignore negative sums from left or right subtree -> Option AQuick Check:
Negative subtree sums must be ignored [OK]
- Not checking for negative subtree sums
- Assuming dfs returns void
- Ignoring null root case
Solution
Step 1: Understand downward path constraint
The path must go downwards from parent to child, so use DFS to explore children.Step 2: Handle negative values
Ignore negative sums by taking max(0, childSum) to avoid reducing path sum.Step 3: Calculate max path sum
At each node, max downward path sum = node.val + max(leftChildSum, rightChildSum, 0).Final Answer:
Use DFS to compute max downward path sum at each node ignoring negative sums by max(0, childSum) -> Option AQuick Check:
Downward path + ignore negatives = DFS with max(0, childSum) [OK]
- Using BFS instead of DFS
- Ignoring negative values incorrectly
- Forcing path through root only
Ready to prove it?
Pass the test and this pattern moves unknown
