LeetCodee

257. Binary Tree Paths

Jump to Solution: Python Java C++ JavaScript C#

Problem Description

Given the root of a binary tree, return all root-to-leaf paths in any order.

A leaf is a node with no children.

Example 1:

Input: root = [1,2,3,null,5]
Output: ["1->2->5","1->3"]

Example 2:

Input: root = [1]
Output: ["1"]

Constraints:

  • The number of nodes in the tree is in the range [1, 100]
  • -100 <= Node.val <= 100

Solution

Python Solution

# 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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        def dfs(node, path, paths):
            if not node:
                return
                
            # Add current node to path
            path.append(str(node.val))
            
            # If leaf node, add path to result
            if not node.left and not node.right:
                paths.append('->'.join(path))
            else:
                # Recursively traverse left and right subtrees
                dfs(node.left, path, paths)
                dfs(node.right, path, paths)
                
            # Backtrack by removing current node
            path.pop()
            
        paths = []
        dfs(root, [], paths)
        return paths

Time Complexity: O(n)

Where n is the number of nodes. We visit each node once.

Space Complexity: O(h)

Where h is the height of the tree, for the recursive call stack and path storage.

Java Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List binaryTreePaths(TreeNode root) {
        List paths = new ArrayList<>();
        if (root == null) {
            return paths;
        }
        
        dfs(root, "", paths);
        return paths;
    }
    
    private void dfs(TreeNode node, String path, List paths) {
        // Add current node to path
        path += (path.isEmpty() ? "" : "->") + node.val;
        
        // If leaf node, add path to result
        if (node.left == null && node.right == null) {
            paths.add(path);
            return;
        }
        
        // Recursively traverse left and right subtrees
        if (node.left != null) {
            dfs(node.left, path, paths);
        }
        if (node.right != null) {
            dfs(node.right, path, paths);
        }
    }
}

Time Complexity: O(n)

Where n is the number of nodes. We visit each node once.

Space Complexity: O(h)

Where h is the height of the tree, for the recursive call stack and path storage.

C++ Solution

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector binaryTreePaths(TreeNode* root) {
        vector paths;
        if (!root) {
            return paths;
        }
        
        dfs(root, "", paths);
        return paths;
    }
    
private:
    void dfs(TreeNode* node, string path, vector& paths) {
        // Add current node to path
        path += (path.empty() ? "" : "->") + to_string(node->val);
        
        // If leaf node, add path to result
        if (!node->left && !node->right) {
            paths.push_back(path);
            return;
        }
        
        // Recursively traverse left and right subtrees
        if (node->left) {
            dfs(node->left, path, paths);
        }
        if (node->right) {
            dfs(node->right, path, paths);
        }
    }
};

Time Complexity: O(n)

Where n is the number of nodes. We visit each node once.

Space Complexity: O(h)

Where h is the height of the tree, for the recursive call stack and path storage.

JavaScript Solution

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {string[]}
 */
var binaryTreePaths = function(root) {
    const paths = [];
    if (!root) {
        return paths;
    }
    
    function dfs(node, path) {
        // Add current node to path
        path += (path ? '->' : '') + node.val;
        
        // If leaf node, add path to result
        if (!node.left && !node.right) {
            paths.push(path);
            return;
        }
        
        // Recursively traverse left and right subtrees
        if (node.left) {
            dfs(node.left, path);
        }
        if (node.right) {
            dfs(node.right, path);
        }
    }
    
    dfs(root, '');
    return paths;
};

Time Complexity: O(n)

Where n is the number of nodes. We visit each node once.

Space Complexity: O(h)

Where h is the height of the tree, for the recursive call stack and path storage.

C# Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    public IList BinaryTreePaths(TreeNode root) {
        var paths = new List();
        if (root == null) {
            return paths;
        }
        
        DFS(root, "", paths);
        return paths;
    }
    
    private void DFS(TreeNode node, string path, List paths) {
        // Add current node to path
        path += (path == "" ? "" : "->") + node.val;
        
        // If leaf node, add path to result
        if (node.left == null && node.right == null) {
            paths.Add(path);
            return;
        }
        
        // Recursively traverse left and right subtrees
        if (node.left != null) {
            DFS(node.left, path, paths);
        }
        if (node.right != null) {
            DFS(node.right, path, paths);
        }
    }
}

Time Complexity: O(n)

Where n is the number of nodes. We visit each node once.

Space Complexity: O(h)

Where h is the height of the tree, for the recursive call stack and path storage.

Approach Explanation

The solution uses depth-first search (DFS) to find all root-to-leaf paths:

  1. Key Insight:
    • Use DFS to traverse from root to leaves
    • Maintain current path during traversal
    • Add path to result when reaching a leaf
  2. Algorithm Steps:
    • Start DFS from root node
    • For each node:
      • Add current node value to path
      • If leaf node, add path to result
      • Otherwise, recurse on children
    • Return all collected paths

Example walkthrough for [1,2,3,null,5]:

  • Start at root (1)
  • Path "1", go left to 2:
    • Path "1->2", go right to 5
    • Path "1->2->5" (leaf), add to result
  • Back to root, go right to 3:
    • Path "1->3" (leaf), add to result

Key insights:

  • DFS ensures complete paths
  • String concatenation vs array joining
  • Path maintenance during recursion
  • Leaf node detection