# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
def dfs(node, current):
if not node:
return 0
current = current * 10 + node.val
if not node.left and not node.right:
return current
return dfs(node.left, current) + dfs(node.right, current)
return dfs(root, 0)
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
int sumNumbers(TreeNode* root) {
return dfs(root, 0);
}
int dfs(TreeNode* node, int current) {
if (!node) return 0;
current = current * 10 + node->val;
if (!node->left && !node->right) return current;
return dfs(node->left, current) + dfs(node->right, current);
}
};
// Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
public int sumNumbers(TreeNode root) {
return dfs(root, 0);
}
private int dfs(TreeNode node, int current) {
if (node == null) return 0;
current = current * 10 + node.val;
if (node.left == null && node.right == null) return current;
return dfs(node.left, current) + dfs(node.right, current);
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var sumNumbers = function(root) {
function dfs(node, current) {
if (!node) return 0;
current = current * 10 + node.val;
if (!node.left && !node.right) return current;
return dfs(node.left, current) + dfs(node.right, current);
}
return dfs(root, 0);
};
Given a binary tree where each node contains a single digit (from 0
to 9
), each root-to-leaf path represents a number formed by concatenating the digits along the path. The task is to find the total sum of all such numbers formed from root to leaf paths in the tree.
For example, if a path from root to leaf is 1 -> 2 -> 3
, it represents the number 123
. You must sum all such numbers for every root-to-leaf path.
To solve this problem, we need to explore all paths from the root to every leaf in the binary tree. For each path, we construct a number by concatenating the digits we encounter. At every leaf node, we add the resulting number to our total sum.
A brute-force way would be to generate all possible paths as lists, convert each to a number, and sum them up. However, this can be optimized by building the number as we traverse the tree, passing the current value down to child nodes. This avoids extra space and repeated computation.
The key insight is to use depth-first search (DFS), carrying the "current number so far" as we go deeper, and only adding to the sum when we reach a leaf node.
The elegant solution uses recursion and DFS. Here’s how it works step by step:
0
.
10
and adding the node's digit value. This mimics "appending" the digit.
null
), return the current number. This number represents one complete root-to-leaf path.
This approach is efficient because:
Consider the following binary tree:
1 / \ 2 3
Step-by-step traversal:
1
, current number is 1
.2
: current number becomes 1 * 10 + 2 = 12
. Node 2
is a leaf, so add 12
to sum.3
: current number becomes 1 * 10 + 3 = 13
. Node 3
is a leaf, so add 13
to sum.12 + 13 = 25
.The process recursively builds each number as it descends, and only adds to the sum at leaf nodes.
O(NL)
, where N
is the number of nodes and L
is the maximum path length (since you might store each path).
O(NL)
for storing all root-to-leaf paths.
O(N)
because each node is visited once.
O(H)
, where H
is the height of the tree, due to the recursion stack.
This makes the DFS solution both time and space efficient.
The key to solving the Sum Root to Leaf Numbers problem is recognizing that you can build each number incrementally as you traverse the tree, and only need to sum the numbers at the leaves. By using a simple DFS recursion, you avoid unnecessary storage and repeated computation, resulting in an elegant and efficient solution that is easy to implement in any language.