Binary Tree Paths

Easy Recursion & Backtracking Basic Recursion Original on LeetCode

Binary Tree Paths is a easy recursion & backtracking problem solved with the basic recursion pattern. The best approach, backtracking with one shared stringbuilder, runs in O(n · h) time and O(h) space. Below are 2 approaches in Java, from dfs building new strings up.

Problem

Return every root-to-leaf path in a binary tree, formatted like "1->2->5", in any order.

Examples

Example 1

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

Example 2

Input
root = [7]
Output
["7"]

Constraints

  • The tree has 1 to 100 nodes.

Animated walkthrough

A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.

Concepts first, then the problem and every approach, step by step.

Space to play or pause · ← → to jump a step · click or drag the bar to seek

Solutions

Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.

ApproachTimeSpace
DFS building new stringsO(n · h)O(n · h)
Backtracking with one shared StringBuilderO(n · h)O(h)

1DFS building new strings

TimeO(n · h)Each string copy costs up to h characters.
SpaceO(n · h)

Pass the path as a string. Each call makes a new string, so nothing needs undoing.

  1. path += node.val; at a leaf, add path.
  2. Otherwise recurse with path + "->".
Java
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> out = new ArrayList<>();
        dfs(root, "", out);
        return out;
    }

    private void dfs(TreeNode node, String path, List<String> out) {
        if (node == null) return;
        path += node.val;
        if (node.left == null && node.right == null) { out.add(path); return; }
        dfs(node.left, path + "->", out);
        dfs(node.right, path + "->", out);
    }
}

2Backtracking with one shared StringBuilder

TimeO(n · h)Copying a path into the answer still costs O(h) per leaf.
SpaceO(h)Recursion depth plus one builder, not counting the output.

Append to a single StringBuilder on the way down and cut it back to its previous length on the way up. This is the choose / explore / un-choose template on a tree.

  1. len = sb.length(); append val (and '->' when not the root).
  2. At a leaf, record sb.toString().
  3. Recurse left and right, then sb.setLength(len).
Java
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> out = new ArrayList<>();
        dfs(root, new StringBuilder(), out);
        return out;
    }

    private void dfs(TreeNode node, StringBuilder sb, List<String> out) {
        if (node == null) return;
        int len = sb.length();
        if (len > 0) sb.append("->");
        sb.append(node.val);
        if (node.left == null && node.right == null) out.add(sb.toString());
        else {
            dfs(node.left, sb, out);
            dfs(node.right, sb, out);
        }
        sb.setLength(len);
    }
}

Edge cases to test

  • Single node
  • Negative values
  • A node with only one child is not a leaf

Hints

Hint 1

Carry the path down the tree; record it only at a leaf (no children).

FAQ

What is the best time complexity for Binary Tree Paths?

Backtracking with one shared StringBuilder runs in O(n · h) time and O(h) extra space. Copying a path into the answer still costs O(h) per leaf.

Which pattern does Binary Tree Paths use?

It is a recursion & backtracking problem that uses the basic recursion pattern. Other problems with the same pattern: Factorial of a number, Fibonacci Number, Binary Tree Inorder Traversal (Recursive).

Is there a brute force solution for Binary Tree Paths?

Yes. DFS building new strings takes O(n · h) time and O(n · h) space. Pass the path as a string.

Which edge cases should I test for Binary Tree Paths?

Single node; Negative values; A node with only one child is not a leaf.