124. Binary Tree Maximum Path Sum¶
Edited by Charles
Hard · Python · Binary Search
Problem
Read the original problem on LeetCode.
The official page contains the problem statement, examples, and constraints.
Explanation, examples & other approaches
Core idea
Given the root of a binary tree, return the maximum path sum of any non-empty path.
A path is a sequence of nodes where each pair of adjacent nodes has an edge connecting them.
Original study notes follow, including intermediate snippets and earlier attempts.
Problem¶
Given the root of a binary tree, return the maximum path sum of any non-empty path.
A path is a sequence of nodes where each pair of adjacent nodes has an edge connecting them.
A node can appear in the path at most once.
The path does not need to pass through the root.
Example¶
The maximum path is:
Therefore:
Output:
The key idea is to distinguish between two different values:
- The complete path through the current node, which is used to update the global maximum.
- The one-sided path starting from the current node, which is returned to its parent.
This distinction is necessary because a valid path cannot branch.
Define:
as:
The maximum path sum starting from
nodeand going downward along only one branch.
Suppose:
From 20, there are two possible paths that can be returned upward:
or:
We choose the larger one:
Therefore:
Suppose 20 has a parent:
If 20 returned both sides:
and then the parent 10 tried to connect to it, we would get:
This is a Y-shaped structure, not a path.
A valid path cannot branch.
Therefore, when returning information to the parent, the current node can choose only:
or:
So:
Although we cannot return both sides to the parent, the current node itself can be the highest point of a complete path.
For example:
A valid complete path is:
Therefore, at the current node, we calculate:
For this example:
This path cannot be extended upward anymore, but it may be the answer to the entire problem.
Therefore, we use it to update the global maximum:
This is the most important distinction in this problem.
Complete Path¶
Used to update the final answer:
Graphically:
or:
Both sides can be used because the path ends at the current subtree.
Returned Path¶
Used by the parent:
Graphically:
or:
Only one side can be selected because the parent may continue the path upward.
Comparison¶
Complete path:
left → node → right
node.val + left + right
Used to:
Update global answer
Returned path:
node → left
OR
node → right
node.val + max(left, right)
Used to:
Return to parent
A simple way to remember:
At every node, we need to know:
before we can calculate the answer for the current node.
Therefore, the processing order is:
which is exactly Postorder Traversal.
Suppose:
If we include the left subtree:
But simply taking:
is better.
Therefore, if a subtree contributes a negative value, we should ignore it.
We write:
This means:
In other words:
We use:
instead of:
because all node values could be negative.
For example:
The correct answer is:
If we initialize:
then the result would incorrectly remain:
Therefore:
allows negative answers.
Consider:
Node 9¶
Both children are empty:
Complete path:
Update:
Return:
Node 15¶
Complete path:
Return:
Node 7¶
Complete path:
Return:
Node 20¶
Now:
Complete path:
Sum:
Update:
But the value returned to -10 can only use one side:
So:
Node 10¶
We receive:
Complete path through -10:
Compare with the existing answer:
Therefore:
For every node:
node
/ \
left right
↓ DFS ↓
left = max(0, dfs(node.left))
right = max(0, dfs(node.right))
↓
Complete path through node:
left + node.val + right
↓
Update global answer:
self.res = max(
self.res,
node.val + left + right
)
↓
Return a one-sided path:
node.val + max(left, right)
↓
Parent
There are only two formulas that need to be remembered.
Formula 1 — Update Global Answer¶
Meaning:
Both sides can be included.
Formula 2 — Return to Parent¶
Meaning:
or:
Only one side can be included.
Time Complexity¶
Each node is visited exactly once:
where n is the number of nodes.
Space Complexity¶
The recursion stack depends on the height of the tree:
For a balanced tree:
For a completely skewed tree:
The core of LeetCode 124 is understanding that the value used to update the answer and the value returned to the parent are different.
while:
Remember:
That is the key idea behind LeetCode 124.
Study record
| Field | Value |
|---|---|
| Attempts | 1 |
| Mastery | ❚ |
| The Latest Attempt | September 9, 2026 |
Python solution¶
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
self.res = float('-inf')
def dfs(node):
if not node:
return 0
left = max(0, dfs(node.left))
right = max(0, dfs(node.right))
self.res = max(
self.res,
node.val + left + right
)
return node.val + max(left, right)
dfs(root)
return self.res