4.3. list of depths
This commit is contained in:
parent
06e9adaba4
commit
8c1c109188
|
|
@ -0,0 +1,67 @@
|
|||
# 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.
|
||||
Loading…
Reference in New Issue