Problem
Given a binary tree where every node contains a single digit (0โ9), each root-to-leaf path spells out a number by concatenating the digits from top to bottom. Return the total sum of all these path numbers.
[4,9,0,5,1]
- Input: root = [4, 9, 0, 5, 1]
- Output: 1026
- Explanation: The three paths are 4โ9โ5 = 495, 4โ9โ1 = 491, and 4โ0 = 40, summing to 1026.
A simpler example with root = [1, 2, 3] gives paths 1โ2 = 12 and 1โ3 = 13, totaling 25.
Intuition
Each path from root to leaf forms a multi-digit number where the root contributes the most significant digit. As you go deeper, the accumulated value shifts one decimal place left โ the same operation as parsing a number digit by digit. Only a true leaf (no children at all) marks the end of a complete path number that can be added to the total.
Solution โ DFS
Perform a depth-first traversal while carrying the number built so far. At each node, shift the running total left one decimal place and add the node's digit. Once a leaf is reached, the number is complete and counts toward the answer.
- Define a recursive helper that takes the current node and the number accumulated on the path so far.
- If the node is null, return 0 โ this handles missing children without special cases above.
- Extend the running number:
current_number = current_number * 10 + node.val. - If the node is a leaf (both children are null), return
current_numberโ the path is complete. - Otherwise, recurse on both subtrees and return the sum of their results.
- Kick off the helper on the root with an initial value of 0.
1class Solution:
2 def sumNumbers(self, root: Optional[TreeNode]) -> int:
3 def dfs(node, current_number):
4 if not node:
5 return 0
6 current_number = current_number * 10 + node.val
7 if not node.left and not node.right: # leaf: path is complete
8 return current_number
9 return dfs(node.left, current_number) + dfs(node.right, current_number)
10
11 return dfs(root, 0)Time: O(n) โ every node is visited exactly once.
Space: O(h) โ the call stack is as deep as the tree's height; O(n) worst case for a skewed tree, O(log n) for a balanced one.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| DFS | O(n) | O(h) | Always โ a single DFS pass is optimal for this problem. |
Common Mistakes
- Treating a one-child node as a leaf โ a leaf requires both children to be null. Returning
current_numberwhen only one child is null cuts off valid paths and under-counts the total. - Adding instead of shifting โ writing
current_number + node.valinstead ofcurrent_number * 10 + node.valsums digits rather than building a decimal number, producing a completely wrong result. - Accumulating paths in a mutable list without backtracking โ if you append digit-by-digit to a shared list and forget to pop after recursing, later paths pick up stale digits from earlier ones.
- Checking for null before multiplying โ some solutions guard
if node is None: return 0at the top but then never reach the leaf check for a node that has exactly one null child, accidentally counting internal nodes as leaves. - Integer overflow on very deep trees โ nodes can have values 0โ9 and paths can be arbitrarily long; at depth 13 the running number can exceed a 32-bit int. Use
longin Java for safety; Python integers are unbounded.
Related Problems
Path Sumโ same root-to-leaf DFS structure, but checks whether the accumulated sum equals a target instead of returning its decimal valuePath Sum IIโ collect every root-to-leaf path whose node sum matches a target, requiring explicit path tracking with backtrackingPath Sum IIIโ paths that don't have to start at the root or end at a leaf, demanding a prefix-sum approach on top of tree DFSBinary Tree Maximum Path Sumโ maximise the sum across any path through the tree, requiring each DFS call to return only the best single-branch contributionBinary Tree Right Side Viewโ BFS or DFS to collect one value per depth level, practicing the same "carry state through traversal" pattern