Given the root
of a binary tree, return all root-to-leaf paths in any order.
A leaf is a node with no children.
For example:
Example 1:
Input: root = [1,2,3,null,5]
Output: ["1->2->5","1->3"]
Example 2:
Input: root = [1]
Output: ["1"]
Constraints:
[1, 100]
.-100 <= Node.val <= 100
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:
The goal is to find all possible routes from the top of a tree to its leaves. The brute force method explores every single path, writing it down as we go. We continue this exhaustive search until we've documented every possible path from the root to a leaf.
Here's how the algorithm would work step-by-step:
def binary_tree_paths(root):
all_paths = []
def find_paths(node, current_path):
if not node:
return
current_path.append(str(node.val))
# Check if the current node is a leaf node.
if not node.left and not node.right:
all_paths.append("->".join(current_path))
else:
# Explore left subtree
find_paths(node.left, current_path)
# Explore right subtree
find_paths(node.right, current_path)
# Backtrack: remove the current node from the path
current_path.pop()
# Initiate path finding from the root
find_paths(root, [])
return all_paths
We need to find every possible route from the top of the tree to its endpoints. We can do this by keeping track of each route as we travel down the tree, adding to the route as we go. When we reach an endpoint, we save the complete route.
Here's how the algorithm would work step-by-step:
class TreeNode:
def __init__(self, value=0, left=None, right=None):
self.value = value
self.left = left
self.right = right
def binary_tree_paths(root):
all_paths = []
def get_paths(node, current_path):
if not node:
return
current_path += str(node.value)
# If it's a leaf, save the path and stop.
if not node.left and not node.right:
all_paths.append(current_path)
return
current_path += "->"
# Explore the left subtree
if node.left:
get_paths(node.left, current_path)
# Explore the right subtree
if node.right:
get_paths(node.right, current_path)
get_paths(root, "")
return all_paths
Case | How to Handle |
---|---|
Null root node | Return an empty list if the root is null as there are no paths. |
Single node tree (root only) | Return a list containing the string representation of the root's value. |
Large, balanced tree | Ensure the solution's space complexity, especially due to recursion or string concatenation, is acceptable and doesn't lead to stack overflow. |
Highly unbalanced (skewed) tree (e.g., left-leaning or right-leaning) | Be mindful of stack depth in recursive solutions; an iterative approach might be preferred for extreme skewness to avoid stack overflow. |
Tree with negative node values | The standard algorithm works correctly with negative values as the path construction is based on node traversal, not value comparisons. |
Tree with zero node values | The standard algorithm works correctly with zero values as the path construction is based on node traversal, not value comparisons. |
Very large integer node values approaching integer limits | String conversion of very large integers should be checked for potential overflow or formatting issues depending on the language used. |
Deeply nested tree approaching system stack limits | Consider converting the recursive solution to an iterative one using a stack data structure to avoid exceeding call stack limits. |