Maximum Path Sum in Binary Tree in DSA Go - 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.
func maxPathSum(root *TreeNode) int {
maxSum := math.MinInt32
var dfs func(node *TreeNode) int
dfs = func(node *TreeNode) int {
if node == nil {
return 0
}
left := max(0, dfs(node.Left))
right := max(0, dfs(node.Right))
maxSum = max(maxSum, left + right + node.Val)
return max(left, right) + node.Val
}
dfs(root)
return maxSum
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
This code finds the maximum sum of any path in a binary tree by visiting each node once and calculating sums from its children.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive depth-first search (dfs) visits each node once.
- How many times: Exactly once per node in the tree.
Each node is visited once, so the total steps grow directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits |
| 100 | About 100 visits |
| 1000 | About 1000 visits |
Pattern observation: The work grows linearly as the tree size increases.
Time Complexity: O(n)
This means the time to find the maximum path sum grows in direct proportion to 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 from children are reused immediately, so no repeated work happens.
Understanding this linear time complexity helps you explain why your solution is efficient and suitable for large trees, a skill valued in interviews.
"What if the tree was a linked list (all nodes have only one child)? How would the time complexity change?"
Practice
Maximum Path Sum in a binary tree mean?Solution
Step 1: Understand the path definition
The path can start and end at any two nodes, not necessarily root or leaf.Step 2: Identify maximum sum meaning
We look for the path with the highest total sum of node values.Final Answer:
The largest sum of values along any path between two nodes in the tree -> Option AQuick Check:
Maximum path sum means highest sum between any two nodes [OK]
- Thinking path must start at root
- Confusing maximum path sum with total tree sum
- Assuming path must end at leaf
type TreeNode struct { Val int; Left, Right *TreeNode }?Solution
Step 1: Check parameter type
Function should accept pointer to TreeNode to avoid copying the whole tree.Step 2: Check return type
Maximum path sum is an integer value, so return type should be int.Final Answer:
func maxPathSum(root *TreeNode) int -> Option AQuick Check:
Pointer input and int output for max path sum [OK]
- Passing TreeNode by value causing copies
- Returning pointer instead of int
- Returning string instead of int
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func maxPathSum(root *TreeNode) int {
maxSum := -1 << 31
var maxGain func(node *TreeNode) int
maxGain = func(node *TreeNode) int {
if node == nil {
return 0
}
leftGain := max(0, maxGain(node.Left))
rightGain := max(0, maxGain(node.Right))
priceNewPath := node.Val + leftGain + rightGain
if priceNewPath > maxSum {
maxSum = priceNewPath
}
return node.Val + max(leftGain, rightGain)
}
maxGain(root)
return maxSum
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
root := &TreeNode{Val: -10}
root.Left = &TreeNode{Val: 9}
root.Right = &TreeNode{Val: 20}
root.Right.Left = &TreeNode{Val: 15}
root.Right.Right = &TreeNode{Val: 7}
fmt.Println(maxPathSum(root))
}Solution
Step 1: Trace maxGain for each node
Calculate max gain from left and right subtree ignoring negatives: - Node 9: maxGain = 9 - Node 15: maxGain = 15 - Node 7: maxGain = 7 - Node 20: maxGain = 20 + max(15,7) = 35 - Root -10: maxGain = -10 + max(9,35) = 25 Check maxSum updates: - At node 9: maxSum = 9 - At node 15: maxSum = 15 - At node 7: maxSum = 15 (unchanged) - At node 20: priceNewPath = 20 + 15 + 7 = 42, maxSum = 42 - At root: priceNewPath = -10 + 9 + 35 = 34 (maxSum stays 42)Step 2: Return maxSum
maxSum is 42 after full traversal.Final Answer:
42 -> Option BQuick Check:
Max path sum = 42 [OK]
- Not ignoring negative gains
- Returning max gain instead of max path sum
- Miscomputing path sums including negative nodes
func maxPathSum(root *TreeNode) int {
maxSum := -1 << 31
var maxGain func(node *TreeNode) int
maxGain = func(node *TreeNode) int {
if node == nil {
return 0
}
leftGain := maxGain(node.Left)
rightGain := maxGain(node.Right)
priceNewPath := node.Val + leftGain + rightGain
if priceNewPath > maxSum {
maxSum = priceNewPath
}
return node.Val + max(leftGain, rightGain)
}
maxGain(root)
return maxSum
}Solution
Step 1: Analyze gain calculation
The function uses leftGain and rightGain directly without ignoring negative values, which can reduce the path sum.Step 2: Identify fix
To fix, use max(0, leftGain) and max(0, rightGain) to ignore negative gains.Final Answer:
It does not ignore negative gains from left or right subtrees -> Option CQuick Check:
Negative gains must be ignored for correct max path sum [OK]
- Not ignoring negative subtree sums
- Wrong initial maxSum value
- Returning before traversal completes
Solution
Step 1: Understand negative values impact
Negative node values can reduce path sums, so ignoring negative gains is necessary.Step 2: Choose correct approach
Use recursion with max(0, gain) and update max sum including both children uses recursion with max(0, gain) to ignore negative paths and updates max sum considering both left and right children plus current node, which correctly finds maximum path sum anywhere in the tree.Final Answer:
Use recursion with max(0, gain) and update max sum including both children -> Option DQuick Check:
Ignore negative gains and consider all paths for max sum [OK]
- Summing all nodes ignoring path constraints
- Only considering root-to-leaf paths
- Returning max node value instead of path sum
Ready to prove it?
Pass the test and this pattern moves unknown
