# 112. Path Sum

LeetCode problem link (opens new window)

Given a binary tree and a target sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the target sum.

Note: A leaf is a node with no children.

Example: Given the following binary tree, and sum = 22,

Return true, as there exists a root-to-leaf path 5->4->11->2 which equals the target sum 22.

# Solution

I believe many of you are wondering when a recursive function needs a return value and when it doesn't, especially when the return type of the recursive function is bool.

I will explain this through a detailed discussion of the following two problems:

In this problem, we want to traverse paths from the root to leaflet nodes and check if the path sum equals the target sum.

# Recursion

We can use a depth-first search approach (preorder, inorder, and postorder all work for this problem as the middle node doesn't have any specific logic) to traverse the binary tree.

  1. Determine the parameters and return type of the recursive function

Parameters: We need the root of the binary tree and an accumulator to track whether the sum of a path equals the target sum. The accumulator should be of type int.

Regarding return type, when does a recursive function need a return type? When doesn't it? Here are three points to summarize:

  • If you need to traverse the entire binary tree without processing the return value of the recursion, the recursive function should not have a return value. (This is the case in Part 2 of this text, in 113. Path Sum II (opens new window))
  • If you need to traverse the entire binary tree and handle the return value of recursion, the recursive function needs a return value. (This is discussed in the solution for 0236. Lowest Common Ancestor of a Binary Tree (opens new window))
  • If you need to find one path that meets the condition, the recursive function must have a return value, because as soon as you find one, you should return immediately. (This is the case in this problem)

In this problem, we need to find one path that meets the condition, so the recursive function should have a boolean return type to promptly return when we find a valid path.

So the code can be like:

bool traversal(TreeNode* cur, int count)   // Note the return type of the function
1
  1. Determine the termination condition

How do we calculate the path sum using the accumulator?

Rather than gathering and comparing with the target sum, we can decrement the accumulator, starting it with the target sum, and subtract the values of the path nodes as we traverse.

If count == 0 and we've reached a leaf node, we found the target sum. If not, and we've reached a leaf node, it means we didn't find the path.

The recursive termination conditions can be coded as follows:

if (!cur->left && !cur->right && count == 0) return true; // reach a leaf node and the count is zero
if (!cur->left && !cur->right) return false; // reached a leaf node without finding a valid path
1
2
  1. Determine the logic within one level of recursion

Because the termination condition considers leaf nodes, we shouldn't let null nodes enter the recursion process.

The recursive function returns a value, and if it returns true, it means a valid path was found and should return immediately.

The code can be illustrated as:

if (cur->left) { // Traverse the left (ignoring null nodes)
    // Immediately return true if a leaf node returns true
    if (traversal(cur->left, count - cur->left->val)) return true; // Note the backtracking logic
}
if (cur->right) { // Traverse the right (ignoring null nodes)
    // Immediately return true if a leaf node returns true
    if (traversal(cur->right, count - cur->right->val)) return true; // Note the backtracking logic
}
return false;
1
2
3
4
5
6
7
8
9

In the above code, backtracking logic is embedded. Without backtracking, we can't look for other paths.

Backtracking is hidden in traversal(cur->left, count - cur->left->val). Because count - cur->left->val is passed as the parameter directly, the count value remains unchanged when the function ends.

To explicitly show the backtracking process, the code can be enhanced like:

if (cur->left) { // Left
    count -= cur->left->val; // recursive, process the node
    if (traversal(cur->left, count)) return true;
    count += cur->left->val; // backtrack, undo the processed result
}
if (cur->right) { // Right
    count -= cur->right->val;
    if (traversal(cur->right, count)) return true;
    count += cur->right->val;
}
return false;
1
2
3
4
5
6
7
8
9
10
11

The complete code is as follows:

class Solution {
private:
    bool traversal(TreeNode* cur, int count) {
        if (!cur->left && !cur->right && count == 0) return true; // reach a leaf node and the count is zero
        if (!cur->left && !cur->right) return false; // reached a leaf node without finding a valid path

        if (cur->left) { // Left
            count -= cur->left->val; // recursive, process the node
            if (traversal(cur->left, count)) return true;
            count += cur->left->val; // backtrack, undo the processed result
        }
        if (cur->right) { // Right
            count -= cur->right->val; // recursive, process the node
            if (traversal(cur->right, count)) return true;
            count += cur->right->val; // backtrack, undo the processed result
        }
        return false;
    }

public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (root == NULL) return false;
        return traversal(root, sum - root->val);
    }
};
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

After refining, the code becomes:

class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (!root) return false;
        if (!root->left && !root->right && sum == root->val) {
            return true;
        }
        return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
    }
};
1
2
3
4
5
6
7
8
9
10

Realize that once the code is refined, the detailed analysis process might not be visible. Ensure to understand the problem clearly before proceeding with code refinement! This is a point I emphasized many times!

# Iteration

If using a stack to simulate recursion, how to backtrack?

At this point, an element in the stack must record not only the pointer to the node but also the sum of the path from the root node to that node.

In C++, we can use a pair structure to store the elements in the stack.

Define it as pair<TreeNode*, int> - a pair of a node pointer and the path sum.

The following code simulates preorder traversal using a stack (detailed comments included):

class Solution {

public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (root == NULL) return false;
        // At this point, the stack must have elements of type pair<Node pointer, Path value>
        stack<pair<TreeNode*, int>> st;
        st.push(pair<TreeNode*, int>(root, root->val));
        while (!st.empty()) {
            pair<TreeNode*, int> node = st.top();
            st.pop();
            // If the current node is a leaf and the path sum equals sum, return true
            if (!node.first->left && !node.first->right && sum == node.second) return true;

            // Right node: when pushing a node, also record the path sum to the node
            if (node.first->right) {
                st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));
            }

            // Left node: when pushing a node, also record the path sum to the node
            if (node.first->left) {
                st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));
            }
        }
        return false;
    }
};
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

Once you thoroughly understand the recursive method for this problem, you can also address 113. Path Sum II (opens new window).

# 113. Path Sum II

LeetCode problem link (opens new window)

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.

Note: A leaf is a node with no children.

Example: Given the following binary tree and sum = 22,

113. Path Sum II

# Solution

  1. Path Sum II needs to traverse the entire tree to find all paths, so the recursive function should not have a return value!

As shown in the diagram:

113. Path Sum II

To illustrate the steps as clearly as possible, here is a code snippet that is not necessarily concise but very clear in logic:

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    // The recursive function does not need to return a value because we need to traverse the entire tree
    void traversal(TreeNode* cur, int count) {
        if (!cur->left && !cur->right && count == 0) { // reach leaf and a path sum found
            result.push_back(path);
            return;
        }

        if (!cur->left && !cur->right) return; // reach leaf with path sum not found

        if (cur->left) { // Left (ignore null nodes)
            path.push_back(cur->left->val);
            count -= cur->left->val;
            traversal(cur->left, count);    // recursion
            count += cur->left->val;        // backtracking
            path.pop_back();                // backtracking
        }
        if (cur->right) { // Right (ignore null nodes)
            path.push_back(cur->right->val);
            count -= cur->right->val;
            traversal(cur->right, count);   // recursion
            count += cur->right->val;       // backtracking
            path.pop_back();                // backtracking
        }
        return;
    }

public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        result.clear();
        path.clear();
        if (root == NULL) return result;
        path.push_back(root->val); // Add root to path
        traversal(root, sum - root->val);
        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
40

As for the iterative method for 113. Path Sum II (opens new window) I've not included it, as it becomes more cumbersome using iteration for tracking all paths, and it's unnecessary if you fully grasp the recursive method. If you are interested, you could further research this.

# Summary

Through the detailed explanation of 112. Path Sum (opens new window) and 113. Path Sum II (opens new window), we addressed when a recursive function needs a return value and when it doesn't.

These two problems are excellent for mastering this knowledge point. After reading the explanation here and trying the problems, you will better understand the difference between searching an entire tree and finding a specific path.

For 112. Path Sum (opens new window), I provided both recursive and iterative methods, though the iterative approach adds complexity. Mastering the recursive way should suffice!

# Other Language Versions

# Java

  1. Path Sum
class Solution {
   public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        targetSum -= root.val;
        // Leaf node
        if (root.left == null && root.right == null) {
            return targetSum == 0;
        }
        if (root.left != null) {
            boolean left = hasPathSum(root.left, targetSum);
            if (left) {      // already found, return early
                return true;
            }
        }
        if (root.right != null) {
            boolean right = hasPathSum(root.right, targetSum);
            if (right) {     // already found, return early
                return true;
            }
        }
        return false;
    }
}

// lc112 concise method
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {

        if (root == null) return false; // exit if null

        // Leaf node check if meets
        if (root.left == null && root.right == null) return root.val == targetSum;

        // Sums on both sides of the branch
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}
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

Iteration

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        stack1.push(root);
        stack2.push(root.val);
        while(!stack1.isEmpty()) {
            int size = stack1.size();

            for(int i = 0; i < size; i++) {
                TreeNode node = stack1.pop();
                int sum = stack2.pop();

                // If this node is a leaf and the path sum equals targetSum, return true
                if(node.left == null && node.right == null && sum == targetSum) {
                    return true;
                }
                // Right node, push a node while also recording the path sum
                if(node.right != null){
                    stack1.push(node.right);
                    stack2.push(sum + node.right.val);
                }
                // Left node, push a node while also recording the path sum
                if(node.left != null) {
                    stack1.push(node.left);
                    stack2.push(sum + node.left.val);
                }
            }
        }
        return false;
    }
}
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
class Solution {    
    public boolean hasPathSum(TreeNode root, int targetSum) {
        Stack<TreeNode> treeNodeStack = new Stack<>();
        Stack<Integer> sumStack = new Stack<>();

        if(root == null)
            return false;
        treeNodeStack.add(root);
        sumStack.add(root.val);

        while(!treeNodeStack.isEmpty()){
            TreeNode curr = treeNodeStack.peek();
            int tempsum = sumStack.pop();
            if(curr != null){
                treeNodeStack.pop();
                treeNodeStack.add(curr);
                treeNodeStack.add(null);
                sumStack.add(tempsum);
                if(curr.right != null){
                    treeNodeStack.add(curr.right);
                    sumStack.add(tempsum + curr.right.val);
                }
                if(curr.left != null){
                    treeNodeStack.add(curr.left);
                    sumStack.add(tempsum + curr.left.val);
                }
            }else{
                treeNodeStack.pop();
                TreeNode temp = treeNodeStack.pop();
                if(temp.left == null && temp.right == null && tempsum == targetSum)
                    return true;
            }
        }
        return false;
    }
}
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
  1. Path Sum II
class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) return res; // non-null check

        List<Integer> path = new LinkedList<>();
        preOrderDfs(root, targetSum, res, path);
        return res;
    }

    public void preOrderDfs(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> path) {
        path.add(root.val);
        // Reached a leaf node
        if (root.left == null && root.right == null) {
            // Found a path with targetSum
            if (targetSum - root.val == 0) {
                res.add(new ArrayList<>(path));
            }
            return; // if sum not equal, return
        }

        if (root.left != null) {
            preOrderDfs(root.left, targetSum - root.val, res, path);
            path.remove(path.size() - 1); // backtrack
        }
        if (root.right != null) {
            preOrderDfs(root.right, targetSum - root.val, res, path);
            path.remove(path.size() - 1); // backtrack
        }
    }
}
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
// Method 2
class Solution {
    List<List<Integer>> result;
    LinkedList<Integer> path;
    public List<List<Integer>> pathSum (TreeNode root,int targetSum) {
        result = new LinkedList<>();
        path = new LinkedList<>();
        travesal(root, targetSum);
        return result;
    }
    private void travesal(TreeNode root,  int count) {
        if (root == null) return;
        path.offer(root.val);
        count -= root.val;
        if (root.left == null && root.right == null && count == 0) {
            result.add(new LinkedList<>(path));
        }
        travesal(root.left, count);
        travesal(root.right, count);
        path.removeLast(); // backtrack
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Method 3 Unified Iterative DFS
class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> result = new ArrayList<>();
        Stack<TreeNode> nodeStack = new Stack<>();
        Stack<Integer> sumStack = new Stack<>();
        Stack<ArrayList<Integer>> pathStack = new Stack<>();
        if(root == null)
            return result;
        nodeStack.add(root);
        sumStack.add(root.val);
        pathStack.add(new ArrayList<>());

        while(!nodeStack.isEmpty()){
            TreeNode currNode = nodeStack.peek();
            int currSum = sumStack.pop();
            ArrayList<Integer> currPath = pathStack.pop();
            if(currNode != null){
                nodeStack.pop();
                nodeStack.add(currNode);
                nodeStack.add(null);
                sumStack.add(currSum);
                currPath.add(currNode.val);
                pathStack.add(new ArrayList(currPath));
                if(currNode.right != null){
                    nodeStack.add(currNode.right);
                    sumStack.add(currSum + currNode.right.val);
                    pathStack.add(new ArrayList(currPath));
                }
                if(currNode.left != null){
                    nodeStack.add(currNode.left);
                    sumStack.add(currSum + currNode.left.val);
                    pathStack.add(new ArrayList(currPath));
                }
            }else{
                nodeStack.pop();
                TreeNode temp = nodeStack.pop();
                if(temp.left == null && temp.right == null && currSum == targetSum)
                    result.add(new ArrayList(currPath));
            }
        }
        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
40
41
42
43
44

# Python

  1. Path Sum

(version one) Recursion

# 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 traversal(self, cur: TreeNode, count: int) -> bool:
        if not cur.left and not cur.right and count == 0: # found leaf and path sum is zero
            return True
        if not cur.left and not cur.right: # found leaf without valid path
            return False
        
        if cur.left: # Left
            count -= cur.left.val
            if self.traversal(cur.left, count): # recursive, process node
                return True
            count += cur.left.val # backtrack, undo process results
            
        if cur.right: # Right
            count -= cur.right.val
            if self.traversal(cur.right, count): # recursive, process node
                return True
            count += cur.right.val # backtrack, undo process results
            
        return False
    
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if root is None:
            return False
        return self.traversal(root, targetSum - root.val)      
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

(version two) Recursion + Refined

# 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 hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        if not root.left and not root.right and targetSum == root.val:
            return True
        return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)
1
2
3
4
5
6
7
8
9
10
11
12
13

(version three) Iteration

# 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 hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        # Here the stack should contain pairs of <node pointer, path sum>
        st = [(root, root.val)]
        while st:
            node, path_sum = st.pop()
            # If the current node is a leaf node and the path sum equals `sum`, then return True
            if not node.left and not node.right and path_sum == sum:
                return True
            # Right node: when pushing a node, also record the path sum
            if node.right:
                st.append((node.right, path_sum + node.right.val))
            # Left node: when pushing a node, also record the path sum
            if node.left:
                st.append((node.left, path_sum + node.left.val))
        return False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  1. Path Sum II

(version one) Recursion

# 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 __init__(self):
        self.result = []
        self.path = []

    def traversal(self, cur, count):
        if not cur.left and not cur.right and count == 0: # Reached leaf with targetSum path found
            self.result.append(self.path[:])
            return

        if not cur.left and not cur.right: # Reached leaf with no targetSum path
            return

        if cur.left: # Left (skip null nodes)
            self.path.append(cur.left.val)
            count -= cur.left.val
            self.traversal(cur.left, count) # recursive
            count += cur.left.val # backtrack
            self.path.pop() # backtrack

        if cur.right: #  Right (skip null nodes)
            self.path.append(cur.right.val) 
            count -= cur.right.val
            self.traversal(cur.right, count) # recursive
            count += cur.right.val # backtrack
            self.path.pop() # backtrack

        return

    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        self.result.clear()
        self.path.clear()
        if not root:
            return self.result
        self.path.append(root.val) # Add root to path
        self.traversal(root, targetSum - root.val)
        return self.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
40
41
42
43

(version two) Recursion + Refined

# 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 pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        
        result = []
        self.traversal(root, targetSum, [], result)
        return result
    def traversal(self,node, count, path, result):
            if not node:
                return
            path.append(node.val)
            count -= node.val
            if not node.left and not node.right and count == 0:
                result.append(list(path))
            self.traversal(node.left, count, path, result)
            self.traversal(node.right, count, path, result)
            path.pop()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Last updated:: 9/4/2025, 3:19:38 PM
Copyright © 2025 keetcoder