You are given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.
Example 1:
Input: root = [1,2,3], targetSum = 3
Output: trueExplanation: The root-to-leaf path with the target sum is 1 -> 2.
Example 2:
Input: root = [-15,10,20,null,null,15,5,-5], targetSum = 15
Output: trueExplanation: The root-to-leaf path with the target sum is -15 -> 20 -> 15 -> -5.
Example 3:
Input: root = [1,1,0,1], targetSum = 2
Output: falseConstraints:
0 <= The number of nodes in the tree <= 5000.-1000 <= Node.val <= 1000-1000 <= targetSum <= 1000Before attempting this problem, you should be comfortable with:
We traverse the tree from root to leaves, accumulating the sum along the way. When we reach a leaf node, we check if the accumulated sum equals the target. dfs naturally explores all root-to-leaf paths, making it ideal for this problem.
dfs(node, curSum) that returns whether a valid path exists from this node.node is null, return false.node.val to curSum.node is a leaf (no children), return whether curSum == targetSum.true if either has a valid path.dfs(root, 0) to start the search.# 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:
def dfs(node, curSum):
if not node:
return False
curSum += node.val
if not node.left and not node.right:
return curSum == targetSum
return dfs(node.left, curSum) or dfs(node.right, curSum)
return dfs(root, 0)Instead of accumulating a sum, we subtract each node's value from the target. When we reach a leaf, we check if the remaining target is zero. This approach avoids passing an extra parameter and keeps the logic clean.
root is null, return false.root.val from targetSum.root is a leaf, return whether targetSum == 0.true if either subtree finds a valid path.# 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
targetSum -= root.val
return (self.hasPathSum(root.left, targetSum) or
self.hasPathSum(root.right, targetSum) or
(not targetSum and not root.left and not root.right))We can simulate the recursive dfs using an explicit stack. Each stack entry stores a node and the remaining sum needed to reach the target from that node. This approach avoids recursion depth issues for very deep trees.
root is null, return false.(root, targetSum - root.val).true.false.# 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
stack = [(root, targetSum - root.val)]
while stack:
node, curr_sum = stack.pop()
if not node.left and not node.right and curr_sum == 0:
return True
if node.right:
stack.append((node.right, curr_sum - node.right.val))
if node.left:
stack.append((node.left, curr_sum - node.left.val))
return Falsebfs explores the tree level by level. We use a queue to store each node along with the remaining sum needed. When we reach a leaf, we check if the target has been met. BFS guarantees we explore all paths systematically.
root is null, return false.(root, targetSum - root.val).true.false if no valid path is found.# 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
queue = deque([(root, targetSum - root.val)])
while queue:
node, curr_sum = queue.popleft()
if not node.left and not node.right and curr_sum == 0:
return True
if node.left:
queue.append((node.left, curr_sum - node.left.val))
if node.right:
queue.append((node.right, curr_sum - node.right.val))
return FalseA frequent mistake is checking if the current sum equals the target at every node rather than only at leaf nodes. The problem specifically requires a root-to-leaf path, so internal nodes should not trigger a true result even if the running sum matches the target. Always verify that both left and right children are null before comparing sums.
Another pitfall is incorrectly returning true when reaching a null node if targetSum happens to be zero. An empty tree (null root) should return false regardless of the target value. The base case for null nodes should always return false, and the sum check should only occur at actual leaf nodes.