# 4.3. List of depths

> Given a binary tree, create a linked list of all the nodes at each depth. If you have a tree with depth D, create D linked lists

Create a breadth-first search and at each level create a linked list and append. I don't know how to create a breadth-first algorithm.

## Hints

* A hash table or array mapping from level numbers to nodes at that level might also be helpful
* First come up with an algorithm which does both depth-first search and breadth-first search

## Solution

We can transverse the graph any way we want, as long as we know which level we're on. We can slightly modify the pre-order traversal algorithm, where we pass in `level+1` to the next recursive call.

```java
public static void createLevelLinkedList(TreeNode root, ArrayList<LinkedList<TreeNode>> lists, int level) {
    if (root == null) return;
    LinkedList<TreeNode> list = null;
    if (lists.size() == level) { // Level not contained in list
        list = new LinkedList<TreeNode>();
        /* Levels are always traversed in order. So, if this is the first time we've visited level i,
            * we must have seen levels 0 through i - 1. We can therefore safely add the level at the end. */
        lists.add(list);  
    } else {
        list = lists.get(level);
    }
    list.add(root);
    createLevelLinkedList(root.left, lists, level + 1);
    createLevelLinkedList(root.right, lists, level + 1);
}
```

Alternatively, we can also implement a modification of the breadth-first search.

```java
public static ArrayList<LinkedList<TreeNode>> createLevelLinkedList(TreeNode root) {
    ArrayList<LinkedList<TreeNode>> result = new ArrayList<LinkedList<TreeNode>>();

    /* "Visit" the root */
    LinkedList<TreeNode> current = new LinkedList<TreeNode>();
    if (root != null) {
        current.add(root);
    }

    while (current.size() > 0) {
        result.add(current); // Add previous level
        LinkedList<TreeNode> parents = current; // Go to next level
        current = new LinkedList<TreeNode>();
        for (TreeNode parent : parents) {
            /* Visit the children */
            if (parent.left != null) {
                current.add(parent.left);
            }
            if (parent.right != null) {
                current.add(parent.right);
            }
        }
    }

    return result;
}
```

Both algorithms run in O(N) time, but space efficiency? The first option uses O(logN) recursive calls (in a balanced tree), each of which adds a new level to the stack. The second solution, which is iterative doesn't need this extra space.

Both solutions require returning O(N) data. The extra O(logN) used in the first approach is dwarfed by the data that must be returned. So both approaches are equally efficient.
