Problem Statement in English

You’re given a binary tree. Your task is to determine if a root to leaf path exists such that the sum of nodes in the path results in the provided targetSum.


Approach

All we need to do is backtrack, or apply a depth first search. In order to do so we need to use a stack.

Each stack element is made up of 2 parts:

  • the last node we visited (index 0)
  • and the sum of nodes visited so far (index 1)

I’ve used the iterative solution, but I think the recursive one will be prettier with respect to this particular question.


Solution in Python


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 the root is `None`, return `False`
        if not root:
            return False
        # check if the root's `val` is the target, if so, return `True`
        elif root.val == targetSum and not root.left and not root.right:
            return True

        # prepopulate the stack with `root` and its `val`
        stack = [[root, root.val]]

        # run while stack isn't empty
        while stack:
            # we use this to determine the position of the current node we're processing,
            # as once we add its left and right children, we need to remove it
            removeAt = -1

            # just to improve code readability
            top = stack[-1]
            topNode = top[0]
            topSum = top[1]

            # if the node we're processing has a valid `left` child
            if topNode.left:
                s = topSum
                # calculate what the sum will be if we include this node
                s += topNode.left.val

                # if `s` is the desired target
                if s == targetSum:
                    tempNode = topNode.left

                    # check if it's a leaf
                    if not tempNode.left and not tempNode.right:
                        # if so, we've found our answer
                        return True
                    else:
                        # else add this node and the current sum to the stack
                        stack.append([topNode.left, s])
                        # this is because we'll use python negative indexing
                        # to remove the parent of the left child
                        removeAt -= 1
                else:
                    # else add this node and the current sum to the stack
                    stack.append([topNode.left, s])
                    # this is because we'll use python negative indexing
                    # to remove the parent of the left child
                    removeAt -= 1

            # now we just do the same thing for the right child

            # if the node we're processing has a valid `right` child
            if topNode.right:
                s = topSum
                # calculate what the sum will be if we include this node
                s += topNode.right.val

                # if `s` is the desired target
                if s == targetSum:
                    tempNode = topNode.right

                    # check if it's a leaf
                    if not tempNode.left and not tempNode.right:
                        # if so, we've found our answer
                        return True
                    else:
                        # else add this node and the current sum to the stack
                        stack.append([topNode.right, s])
                        # this is because we'll use python negative indexing
                        # to remove the parent of the right child
                        removeAt -= 1
                else:
                    # else add this node and the current sum to the stack
                    stack.append([topNode.right, s])
                    # this is because we'll use python negative indexing
                    # to remove the parent of the right child
                    removeAt -= 1

            # use `removeAt` to remove the parent node we just finished processing
            stack.pop(removeAt)

        # if the stack's empty and we've reached here,
        # then the target doesn't exist
        return False

Complexity

  • Time: $O(n)$
    Since we process atmost $n$ nodes.

  • Space: $O(n)$
    Since we use a stack that can contain atmost $n$ nodes.


Mistakes I Made

I didn’t read the question properly, and failed to notice that we’re only supposed to return root to leaf paths whose sum is the desired target.


And we are done.