Path Sum Root to Leaf in Binary Tree in DSA Rust - Time & Space Complexity
We want to know how long it takes to check if a path from the root to a leaf adds up to a target sum.
This helps us understand how the time grows as the tree gets bigger.
Analyze the time complexity of the following code snippet.
fn has_path_sum(root: &Option>, target_sum: i32) -> bool {
match root {
None => false,
Some(node) => {
if node.left.is_none() && node.right.is_none() {
return node.val == target_sum;
}
has_path_sum(&node.left, target_sum - node.val) || has_path_sum(&node.right, target_sum - node.val)
}
}
}
This code checks if any root-to-leaf path sums to the target by exploring each branch recursively.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls visiting each node once.
- How many times: Once per node in the tree.
As the number of nodes grows, the function visits each node once.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits |
| 100 | About 100 visits |
| 1000 | About 1000 visits |
Pattern observation: The work grows directly with the number of nodes.
Time Complexity: O(n)
This means the time to check grows linearly with the number of nodes in the tree.
[X] Wrong: "The function only checks one path, so it runs in constant time."
[OK] Correct: The function explores all possible paths until it finds a match or finishes, so it visits many nodes, not just one path.
Understanding this helps you explain how recursive tree problems scale and shows you can reason about visiting all nodes efficiently.
"What if the tree was balanced vs completely skewed? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem statement
The problem asks if there is any path from the root node down to any leaf node where the sum of the node values equals a given target sum.Step 2: Differentiate from other tree properties
This is different from finding the maximum depth, counting nodes, or summing all nodes. It specifically checks for a path sum.Final Answer:
If there exists a root-to-leaf path with a sum equal to a target value -> Option BQuick Check:
Path sum means root-to-leaf sum check = A [OK]
- Confusing path sum with total tree sum
- Checking any path, not just root-to-leaf
- Mixing depth or node count with sum
struct TreeNode { val: i32, left: Option, right: Option }?Solution
Step 1: Analyze the tree node ownership and option usage
The tree nodes are wrapped inOptionto allow for empty children and heap allocation. The function should acceptOptionto handle empty trees.Step 2: Check return type and parameters
The function returns a boolean indicating if a path sum exists. So the signaturefn has_path_sum(root: Option, sum: i32) -> boolmatches the problem.Final Answer:
fn has_path_sum(root: Option, sum: i32) -> bool -> Option CQuick Check:
Correct ownership and return type = D [OK]
- Using TreeNode directly without Option or Box
- Wrong return type (not bool)
- Passing references incorrectly
struct TreeNode {
val: i32,
left: Option,
right: Option,
}
fn has_path_sum(root: Option, sum: i32) -> bool {
match root {
None => false,
Some(node) => {
if node.left.is_none() && node.right.is_none() {
return node.val == sum;
}
has_path_sum(node.left, sum - node.val) || has_path_sum(node.right, sum - node.val)
}
}
}
fn main() {
let leaf = TreeNode { val: 5, left: None, right: None };
let root = TreeNode {
val: 4,
left: Some(Box::new(leaf)),
right: None,
};
println!("{}", has_path_sum(Some(Box::new(root)), 9));
}Solution
Step 1: Trace the path sum calculation
The tree has root 4 with left child 5. The target sum is 9. The path 4 -> 5 sums to 9, so the function returns true.Step 2: Confirm leaf node check and recursion
At leaf node 5, it checks if 5 == 9 - 4 = 5, which is true, so returns true.Final Answer:
true -> Option DQuick Check:
4 + 5 = 9 matches sum = true [OK]
- Ignoring leaf node condition
- Subtracting sum incorrectly
- Confusing Option handling
fn has_path_sum(root: Option, sum: i32) -> bool {
if root.is_none() {
return false;
}
let node = root.unwrap();
if node.left.is_none() && node.right.is_none() {
return node.val == sum;
}
has_path_sum(node.left, sum - node.val) && has_path_sum(node.right, sum - node.val)
}Solution
Step 1: Analyze recursive call logic
The function uses logical AND (&&) to combine left and right subtree results, but the problem requires checking if any path exists, so logical OR (||) is correct.Step 2: Understand impact of && vs ||
Using && means both left and right paths must have the sum, which is incorrect. Only one path needs to match.Final Answer:
Using && instead of || for recursive calls -> Option AQuick Check:
Path sum needs OR (||), not AND (&&) [OK]
- Using && instead of ||
- Unwrapping Option without safe check
- Ignoring leaf node condition
Solution
Step 1: Understand the requirement for all paths
To find all root-to-leaf paths with a given sum, we need to explore all paths and store those matching the sum.Step 2: Choose backtracking with mutable vectors
Backtracking allows building paths step-by-step, storing current path in a mutable vector, and adding copies to results when sum matches.Final Answer:
Use backtracking with a mutable vector to store current path and a vector of vectors for results -> Option AQuick Check:
Backtracking with path storage = B [OK]
- Using global variables (not idiomatic in Rust)
- Printing instead of returning paths
- Trying BFS which is complex for path tracking
Ready to prove it?
Pass the test and this pattern moves unknown
