Bird
Raised Fist0
DSA Rustprogramming

Maximum Path Sum in Binary Tree in DSA Rust

Choose your learning style10 modes available
Mental Model
Find the highest sum of node values along any path in the tree, where the path can start and end anywhere.
Analogy: Imagine hiking on a mountain range where each peak has a height (node value). You want to find the highest total elevation gain by walking along connected peaks, but you can start and stop anywhere on the trail.
      1
     / \
    2   3
   / \   \
  4  -5   6
Dry Run Walkthrough
Input: Binary tree: 1 -> 2, 3; 2 -> 4, -5; 3 -> null, 6
Goal: Find the maximum path sum anywhere in the tree
Step 1: Start at leaf node 4, max path sum from 4 is 4
Node 4: max_single=4, max_top=4
Why: Leaf nodes have max path sum equal to their own value
Step 2: At node -5, max path sum is -5
Node -5: max_single=-5, max_top=-5
Why: Negative value, path sum is node value itself
Step 3: At node 2, calculate max path including left and right children
Node 2: max_single=max(2, 2+4, 2+(-5))=6, max_top=max(6, 2+4+(-5))=6
Why: Choose best path through node 2, possibly including one or both children
Step 4: At leaf node 6, max path sum is 6
Node 6: max_single=6, max_top=6
Why: Leaf node max path sum is its own value
Step 5: At node 3, max path sum is max(3, 3+6)=9
Node 3: max_single=9, max_top=9
Why: Choose best path including node 3 and its right child
Step 6: At root node 1, calculate max path sum including left and right children
Node 1: max_single=max(1, 1+6, 1+9)=10, max_top=max(10, 1+6+9)=16
Why: Max path can go through root connecting left and right subtrees
Result:
Maximum path sum is 16
Annotated Code
DSA Rust
use std::cmp::{max, min};

#[derive(Debug)]
struct TreeNode {
    val: i32,
    left: Option<Box<TreeNode>>,
    right: Option<Box<TreeNode>>,
}

impl TreeNode {
    fn new(val: i32) -> Self {
        TreeNode { val, left: None, right: None }
    }
}

fn max_path_sum(root: &Option<Box<TreeNode>>) -> i32 {
    fn helper(node: &Option<Box<TreeNode>>, max_sum: &mut i32) -> i32 {
        if node.is_none() {
            return 0;
        }
        let n = node.as_ref().unwrap();
        // Recursively get max path sum from left child
        let left = max(helper(&n.left, max_sum), 0);
        // Recursively get max path sum from right child
        let right = max(helper(&n.right, max_sum), 0);
        // Calculate max path sum passing through current node
        let current_sum = n.val + left + right;
        // Update global max if current path sum is higher
        *max_sum = max(*max_sum, current_sum);
        // Return max path sum including current node and one subtree
        n.val + max(left, right)
    }

    let mut max_sum = i32::MIN;
    helper(root, &mut max_sum);
    max_sum
}

fn main() {
    // Construct the tree:
    //       1
    //      / \
    //     2   3
    //    / \   \
    //   4  -5   6
    let mut root = Box::new(TreeNode::new(1));
    let mut node2 = Box::new(TreeNode::new(2));
    node2.left = Some(Box::new(TreeNode::new(4)));
    node2.right = Some(Box::new(TreeNode::new(-5)));
    let mut node3 = Box::new(TreeNode::new(3));
    node3.right = Some(Box::new(TreeNode::new(6)));
    root.left = Some(node2);
    root.right = Some(node3);

    let result = max_path_sum(&Some(root));
    println!("Maximum path sum is {}", result);
}
let left = max(helper(&n.left, max_sum), 0);
Calculate max path sum from left child, ignore negative sums
let right = max(helper(&n.right, max_sum), 0);
Calculate max path sum from right child, ignore negative sums
let current_sum = n.val + left + right;
Sum path through current node including both children
*max_sum = max(*max_sum, current_sum);
Update global max path sum if current path is better
n.val + max(left, right)
Return max path sum including current node and one subtree
OutputSuccess
Maximum path sum is 16
Complexity Analysis
Time: O(n) because each node is visited once in the recursion
Space: O(h) where h is the tree height due to recursion stack
vs Alternative: Naive approaches checking all paths explicitly are O(n^2) or worse, this uses bottom-up recursion for efficiency
Edge Cases
Empty tree
Returns minimum integer value as no path exists
DSA Rust
if node.is_none() { return 0; }
All negative values
Ignores negative child paths, returns max single node value
DSA Rust
let left = max(helper(&n.left, max_sum), 0);
Single node tree
Returns the node value itself
DSA Rust
if node.is_none() { return 0; }
When to Use This Pattern
When asked to find the maximum sum path in a tree that can start and end anywhere, use a recursive bottom-up approach that tracks max sums including and passing through nodes.
Common Mistakes
Mistake: Not ignoring negative sums from children, which lowers the max path sum
Fix: Use max(child_sum, 0) to ignore negative paths
Mistake: Returning sum including both children instead of only one child for recursion return
Fix: Return node value plus max of left or right child sums, not both
Summary
Finds the highest sum of values along any path in a binary tree.
Use when you need the max path sum that can start and end anywhere in the tree.
The key is to track max sums including one child for recursion and update global max including both children.

Practice

(1/5)
1. What does the "Maximum Path Sum in Binary Tree" problem ask you to find?
easy
A. The longest path length in the binary tree
B. The number of leaf nodes in the binary tree
C. The highest sum of values along any path in the binary tree
D. The minimum value stored in the binary tree

Solution

  1. Step 1: Understand the problem statement

    The problem asks for the maximum sum of node values along any path in the binary tree. A path can start and end at any node, but must be connected through parent-child links.
  2. Step 2: Clarify what a path means

    A path can go downwards or upwards but cannot revisit nodes. The goal is to find the path with the largest sum of node values.
  3. Final Answer:

    The highest sum of values along any path in the binary tree -> Option C
  4. Quick Check:

    Maximum path sum means largest sum of connected nodes [OK]
Hint: Focus on sums of connected nodes, not just length [OK]
Common Mistakes:
  • Confusing path length with path sum
  • Thinking path must start at root
  • Ignoring negative values in nodes
2. Which Rust function signature correctly represents a function to find the maximum path sum in a binary tree node defined as struct TreeNode { val: i32, left: Option, right: Option }?
easy
A. fn max_path_sum(root: Option) -> i32
B. fn max_path_sum(root: TreeNode) -> Option<i32>
C. fn max_path_sum(root: &TreeNode) -> i32
D. fn max_path_sum(root: Option<TreeNode>) -> i32

Solution

  1. Step 1: Understand Rust ownership and option types

    The tree root is usually wrapped in Option to allow for empty nodes and heap allocation.
  2. Step 2: Choose correct function signature

    The function should accept Option and return i32 for the maximum path sum. Passing by value is common for ownership transfer.
  3. Final Answer:

    fn max_path_sum(root: Option) -> i32 -> Option A
  4. Quick Check:

    Option input and i32 output [OK]
Hint: Use Option for nullable tree nodes [OK]
Common Mistakes:
  • Using TreeNode without Box causes size errors
  • Returning Option<i32> unnecessarily
  • Passing root by reference when ownership is needed
3. Given the following Rust code snippet for maximum path sum, what will be the output?
struct TreeNode {
    val: i32,
    left: Option,
    right: Option,
}

fn max_path_sum(root: Option) -> i32 {
    fn helper(node: &Option, max_sum: &mut i32) -> i32 {
        if let Some(n) = node {
            let left = helper(&n.left, max_sum).max(0);
            let right = helper(&n.right, max_sum).max(0);
            *max_sum = (*max_sum).max(n.val + left + right);
            n.val + left.max(right)
        } else {
            0
        }
    }
    let mut max_sum = i32::MIN;
    helper(&root, &mut max_sum);
    max_sum
}

fn main() {
    let root = Some(Box::new(TreeNode {
        val: -10,
        left: Some(Box::new(TreeNode {
            val: 9,
            left: None,
            right: None,
        })),
        right: Some(Box::new(TreeNode {
            val: 20,
            left: Some(Box::new(TreeNode {
                val: 15,
                left: None,
                right: None,
            })),
            right: Some(Box::new(TreeNode {
                val: 7,
                left: None,
                right: None,
            })),
        })),
    }));
    println!("{}", max_path_sum(root));
}
medium
A. 20
B. 35
C. 27
D. 42

Solution

  1. Step 1: Trace recursive helper calls and calculate sums

    Calculate max path sums for left and right subtrees, ignoring negative sums by max(0). For node 20, left=15, right=7, sum=20+15+7=42. For root -10, left max=9, right max=42, total= -10+9+42=41 but max_sum is 42 from node 20 subtree.
  2. Step 2: Determine maximum path sum found

    The maximum path sum is 42 from path 15 -> 20 -> 7.
  3. Final Answer:

    42 -> Option D
  4. Quick Check:

    Max path sum = 42 [OK]
Hint: Ignore negative sums by max(0) to maximize path sum [OK]
Common Mistakes:
  • Including negative sums in path
  • Confusing max path sum with max root-to-leaf sum
  • Miscomputing sums for left and right subtrees
4. Identify the bug in this Rust function snippet for maximum path sum and select the fix:
fn helper(node: &Option, max_sum: &mut i32) -> i32 {
    if let Some(n) = node {
        let left = helper(&n.left, max_sum);
        let right = helper(&n.right, max_sum);
        *max_sum = (*max_sum).max(n.val + left + right);
        n.val + left.max(right)
    } else {
        0
    }
}
medium
A. Add .max(0) to left and right to ignore negative sums
B. Change return type to Option<i32>
C. Remove max_sum parameter and return max sum directly
D. Replace n.val + left.max(right) with n.val + left + right

Solution

  1. Step 1: Identify problem with negative sums

    Without .max(0), negative sums from left or right subtrees reduce the path sum, which is incorrect for maximum path sum calculation.
  2. Step 2: Fix by ignoring negative sums

    Adding .max(0) to left and right ensures negative sums are treated as zero, improving the maximum path sum calculation.
  3. Final Answer:

    Add .max(0) to left and right to ignore negative sums -> Option A
  4. Quick Check:

    Ignore negative sums with max(0) [OK]
Hint: Always ignore negative subtree sums with max(0) [OK]
Common Mistakes:
  • Not handling negative values correctly
  • Changing return type unnecessarily
  • Summing left and right twice
5. You want to modify the maximum path sum function to also return the path nodes (values) that produce the maximum sum. Which approach is best to implement this in Rust?
hard
A. Return only max_sum and reconstruct path by traversing tree again after computation
B. Use a helper function returning a tuple of (max_sum, path_vec) and update global max with path
C. Store paths in a global mutable vector and update it inside recursion without returning
D. Use a stack to store nodes during recursion and pop when max sum is found

Solution

  1. Step 1: Understand need to track path along with sums

    To return the path nodes, the helper must return both the max sum and the path that produces it.
  2. Step 2: Use tuple return and update global max with path

    Returning (max_sum, path_vec) allows updating the global max sum and storing the corresponding path during recursion.
  3. Final Answer:

    Use a helper function returning a tuple of (max_sum, path_vec) and update global max with path -> Option B
  4. Quick Check:

    Return sum and path together for tracking [OK]
Hint: Return both sum and path as tuple from recursion [OK]
Common Mistakes:
  • Using global mutable state without return
  • Recomputing path after sum calculation
  • Using stack incorrectly for path tracking
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard