You are given the root
of a binary tree where each node has a value 0
or 1
. Each root-to-leaf path represents a binary number starting with the most significant bit.
0 -> 1 -> 1 -> 0 -> 1
, then this could represent 01101
in binary, which is 13
.For all leaves in the tree, consider the numbers represented by the path from the root to that leaf. Return the sum of these numbers.
The test cases are generated so that the answer fits in a 32-bits integer.
Example 1:
Input: root = [1,0,1,0,1,0,1] Output: 22 Explanation: (100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
Example 2:
Input: root = [0] Output: 0
Constraints:
[1, 1000]
.Node.val
is 0
or 1
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine walking down every possible path from the top of a tree to each leaf. The brute force method explores all these paths, converting each path into a number, and then summing them up.
Here's how the algorithm would work step-by-step:
def sum_root_to_leaf(root):
total_sum = 0
def dfs(node, current_number):
nonlocal total_sum
if not node:
return
# Update the current number based on the node value.
current_number = (current_number << 1) | node.val
# If it's a leaf node, add the current number to the total.
if not node.left and not node.right:
total_sum += current_number
return
dfs(node.left, current_number)
dfs(node.right, current_number)
dfs(root, 0)
return total_sum
The key is to build the binary number representation as we walk down the tree, rather than waiting to reach the leaf node. This avoids storing or recomputing paths. We keep track of the current number and add the leaf value to form the complete binary number from root to leaf.
Here's how the algorithm would work step-by-step:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def sum_root_to_leaf(root):
total_sum = 0
def calculate_sum(node, current_number):
nonlocal total_sum
if not node:
return
# Shift existing number to make space for new digit.
current_number = (current_number << 1) + node.val
# Leaf node: add the number to running total.
if not node.left and not node.right:
total_sum += current_number
return
# Explore the left and right subtrees.
calculate_sum(node.left, current_number)
calculate_sum(node.right, current_number)
calculate_sum(root, 0)
return total_sum
Case | How to Handle |
---|---|
Null or empty tree | Return 0 immediately, as there are no root-to-leaf paths. |
Single node tree (root only) | Return the root's value directly as the only path sum. |
Tree with all nodes having the value 0 | The sum will be 0, which the algorithm should handle correctly. |
Tree with all nodes having the value 1, resulting in a very large binary number | Be mindful of potential integer overflow; use a larger data type if needed or perform modulo operations. |
Highly unbalanced tree (skewed left or right) | The recursive call stack might become very deep, potentially leading to a stack overflow, so an iterative approach might be preferred for extreme cases. |
Tree where all leaf nodes are at vastly different depths | The algorithm should still correctly calculate the binary number for each path, regardless of depth differences. |
Integer overflow during binary number construction | Use modulo arithmetic with a large prime number to prevent integer overflow and keep the result within manageable bounds. |
Tree with a very large number of nodes | The solution should scale linearly with the number of nodes, but memory usage might become a concern if each node consumes significant memory. |