# 129. Sum Root to Leaf Numbers

LeetCode Problem Link (opens new window)

# Approach

This problem shares a similar approach with 113. Path Sum II (opens new window). After completing this problem, you can also tackle 113. Path Sum II (opens new window) and 112. Path Sum (opens new window).

If you're unsure when a recursive function in a binary tree needs a return value, you might find it helpful to check Binary Tree: When Does a Recursive Function Need a Return Value and When Does It Not? (opens new window).

Once you understand these, this problem becomes much simpler. While addressing this problem, you will actually employ backtracking, though some might not realize they are using backtracking. In Binary Tree: Using Recursion and Discovering Hidden Backtracking (opens new window), I have explained in detail how backtracking is used within recursion in binary tree problems.

Now let's look at the problem:

The idea is clear: traverse the entire tree and sum up the numbers formed from the root node to each leaf node.

We begin by following the three-step approach of recursion:

# Three Steps of Recursion

If you are not familiar with these steps, you can refer to Binary Tree: Preorder, Inorder, and Postorder Traversal Explained (opens new window).

  • Determine the return value and its parameters for the recursive function

Here, we need to traverse the entire binary tree and require a return value to handle logic, so the return type is void. This was discussed in detail in Binary Tree: When Does a Recursive Function Need a Return Value and When Does It Not? (opens new window).

The function should take the root node as its parameter. We also define two global variables, one for the result, and a vector<int> path.

Why use a vector type (array)? Because using a vector simplifies backtracking!

So the code is as follows:

int result;
vector<int> path;
void traversal(TreeNode* cur) 
1
2
3
  • Determine the termination condition

The recursion stops when we reach a leaf node. At this point, we collect the result and move back to the previous level of recursion. Since we're using a vector for a single path, we need a function vectorToInt to convert the vector to an integer.

The termination condition is coded as follows:

if (!cur->left && !cur->right) { // Leaf node reached
    result += vectorToInt(path);
    return;
}
1
2
3
4

Here, the vectorToInt function converts the vector to an integer, as shown below:

int vectorToInt(const vector<int>& vec) {
    int sum = 0;
    for (int i = 0; i < vec.size(); i++) {
        sum = sum * 10 + vec[i];
    }
    return sum;
}
1
2
3
4
5
6
7
  • Determine the single-layer recursive logic

For this problem, it does not matter whether you use preorder, inorder, or postorder traversal, as there is no specific logic to handle for intermediate nodes.

The key point is that when the left node is not null, you record the path and recursively traverse the left child, and similarly for the right node.

And don't forget to backtrack.

Refer to the illustration:

The code is as follows:

                 // Process current node
if (cur->left) { // Traverse left (excluding null nodes)
    path.push_back(cur->left->val);
    traversal(cur->left);    // Recursion
    path.pop_back();         // Backtracking
}
if (cur->right) { // Traverse right (excluding null nodes)
    path.push_back(cur->right->val);
    traversal(cur->right);   // Recursion
    path.pop_back();         // Backtracking
}
1
2
3
4
5
6
7
8
9
10
11

Note that the backtracking and recursion should always be together, a one-to-one relationship. Some might write the code as follows:

if (cur->left) { // Traverse left (excluding null nodes)
    path.push_back(cur->left->val);
    traversal(cur->left);    // Recursion
}
if (cur->right) { // Traverse right (excluding null nodes)
    path.push_back(cur->right->val);
    traversal(cur->right);   // Recursion
}
path.pop_back();         // Backtracking
1
2
3
4
5
6
7
8
9

Placing the backtracking step outside the braces is incorrect.

Complete C++ Code

With the key logic discussed, here is the complete C++ code:

class Solution {
private:
    int result;
    vector<int> path;
    // Convert vector to int
    int vectorToInt(const vector<int>& vec) {
        int sum = 0;
        for (int i = 0; i < vec.size(); i++) {
            sum = sum * 10 + vec[i];
        }
        return sum;
    }
    void traversal(TreeNode* cur) {
        if (!cur->left && !cur->right) { // Leaf node reached
            result += vectorToInt(path);
            return;
        }

        if (cur->left) { // Traverse left (excluding null nodes)
            path.push_back(cur->left->val);     // Process node
            traversal(cur->left);               // Recursion
            path.pop_back();                    // Backtracking, undo
        }
        if (cur->right) { // Traverse right (excluding null nodes)
            path.push_back(cur->right->val);    // Process node
            traversal(cur->right);              // Recursion
            path.pop_back();                    // Backtracking, undo
        }
        return;
    }
public:
    int sumNumbers(TreeNode* root) {
        path.clear();
        if (root == nullptr) return 0;
        path.push_back(root->val);
        traversal(root);
        return result;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# Summary

Overly simplified code can easily obscure the essence of backtracking in this problem, even to the point where the author might not realize they were using backtracking.

The code I provide fully incorporates the backtracking process, aiming to make this clear to everyone!

# Other Language Versions

# Java:

class Solution {
    List<Integer> path = new ArrayList<>();
    int res = 0;
    public int sumNumbers(TreeNode root) {
        // If the node is null, return 0
        if (root == null) return 0;
        // First, add the root node to the collection
        path.add(root.val);
        // Begin recursion
        recur(root);
        return res;
    }

    public void recur(TreeNode root){
        if (root.left == null && root.right == null) {
            // Process when it's a leaf node
            res += listToInt(path);
            return;
        }

        if (root.left != null){
            // Note backtracking
            path.add(root.left.val);
            recur(root.left);
            path.remove(path.size() - 1);
        }
        if (root.right != null){
            // Note backtracking
            path.add(root.right.val);
            recur(root.right);
            path.remove(path.size() - 1);
        }
        return;
    }
    public int listToInt(List<Integer> path){
        int sum = 0;
        for (Integer num:path){
            // sum * 10 indicates a digit place
            sum = sum * 10 + num;
        }
        return sum;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# Python:

class Solution:
    def sumNumbers(self, root: TreeNode) -> int:
        res = 0
        path = []
        def backtrace(root):
            nonlocal res
            if not root: return # If node is null, return
            path.append(root.val)
            if not root.left and not root.right: # Leaf node reached
                res += get_sum(path)
            if root.left: # If left subtree is not null
                backtrace(root.left)
            if root.right: # If right subtree is not null
                backtrace(root.right)
            path.pop()

        def get_sum(arr):
            s = 0
            for i in range(len(arr)):
                s = s * 10 + arr[i]
            return s

        backtrace(root)
        return res
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# Go:

func sumNumbers(root *TreeNode) int {
    sum := 0
    dfs(root, root.Val, &sum)
    return sum
}

func dfs(root *TreeNode, tmpSum int, sum *int) {
    if root.Left == nil && root.Right == nil {
        *sum += tmpSum
    } else {
        if root.Left != nil {
            dfs(root.Left, tmpSum*10 + root.Left.Val, sum)
        }
        if root.Right != nil {
            dfs(root.Right, tmpSum*10 + root.Right.Val, sum)
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# JavaScript:

var sumNumbers = function(root) {
    const listToInt = path => {
        let sum = 0;
        for(let num of path){
            // sum * 10 indicates a digit place
            sum = sum * 10 + num;
        }
        return sum;
    }
    const recur = root =>{
        if (root.left == null && root.right == null) {
            // Process when it's a leaf node
            res += listToInt(path);
            return;
        }

        if (root.left != null){
            // Note backtracking
            path.push(root.left.val);
            recur(root.left);
            path.pop();
        }
        if (root.right != null){
            // Note backtracking
            path.push(root.right.val);
            recur(root.right);
            path.pop();
        }
        return;
    };
    const path = new Array();
    let res = 0;
    // If the node is null, return 0
    if (root == null) return 0;
    // First, add the root node to the collection
    path.push(root.val);
    // Begin recursion
    recur(root);
    return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# TypeScript:

function sumNumbers(root: TreeNode | null): number {
    if (root === null) return 0;
    // Record the final result
    let resTotal: number = 0;
    // Record the node values encountered on the path
    const route: number[] = [];
    // Initial value for recursion
    route.push(root.val);
    recur(root, route);
    return resTotal;
    function recur(node: TreeNode, route: number[]): void {
        if (node.left === null && node.right === null) {
            resTotal += listToSum(route);
            return;
        }
        if (node.left !== null) {
            route.push(node.left.val);
            recur(node.left, route);
            route.pop();
        };
        if (node.right !== null) {
            route.push(node.right.val);
            recur(node.right, route);
            route.pop();
        };
    }
    function listToSum(nums: number[]): number {
        // Sum of the array
        return Number(nums.join(''));
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# C:

//sum records the total
int sum;
void traverse(struct TreeNode *node, int val) {
    // Update val as the sum from the root to the current node
    val = val * 10 + node->val;
    // If the current node is a leaf, record val
    if(!node->left && !node->right) {
        sum+=val;
        return;
    }
    // If there is a left/right node, traverse left/right node
    if(node->left) 
        traverse(node->left, val);
    if(node->right)
        traverse(node->right, val);
}

int sumNumbers(struct TreeNode* root){
    sum = 0;
    
    traverse(root, 0);

    return sum;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Last updated:: 9/4/2025, 3:19:38 PM
Copyright © 2025 keetcoder