Given a binary tree, return the vertical order traversal of its nodes’ values. (ie, from top to bottom, column by column).
Java Solution 1
For each node, its left child’s degree is -1 and is right child’s degree is +1. We can do a level order traversal and save the degree information.
public List<List<Integer>> verticalOrder(TreeNode root) { TreeMap<Integer, ArrayList<Integer>> map = new TreeMap<>(); helper(root, map); List<List<Integer>> result = new ArrayList<>(); result.addAll(map.values()); return result; } private void helper(TreeNode t, TreeMap<Integer, ArrayList<Integer>> map) { if (t == null) { return; } LinkedList<TreeNode> q1 = new LinkedList<>(); LinkedList<Integer> q2 = new LinkedList<>(); q1.offer(t); q2.offer(0); while (!q1.isEmpty()) { TreeNode node = q1.poll(); int order = q2.poll(); //add to map ArrayList<Integer> list = map.get(order); if (list == null) { list = new ArrayList<>(); map.put(order, list); } list.add(node.val); if (node.left != null) { q1.offer(node.left); q2.offer(order - 1); } if (node.right != null) { q1.offer(node.right); q2.offer(order + 1); } } } |
Time complexity is O(n*log(n)) and space complexity is O(n). n is the number of nodes on the tree.
Java Solution 2
The time can be improved by not using TreeMap. We can calculate the min and max order of the tree first. We know that there should not be any gap between any indices.
public List<List<Integer>> verticalOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if(root==null){ return result; } int[] mm = new int[2]; getMinMax(root, mm, 0); int len = mm[1]-mm[0]+1; for(int i=0; i<len; i++){ result.add(new ArrayList<Integer>()); } LinkedList<TreeNode> q1 = new LinkedList<>(); LinkedList<Integer> q2 = new LinkedList<>(); q1.offer(root); q2.offer(0); while(!q1.isEmpty()){ TreeNode h = q1.poll(); int order = q2.poll(); result.get(order-mm[0]).add(h.val); if(h.left!=null){ q1.offer(h.left); q2.offer(order-1); } if(h.right!=null){ q1.offer(h.right); q2.offer(order+1); } } return result; } private void getMinMax(TreeNode node, int[] mm, int order){ if(node == null){ return; } mm[0] = Math.min(mm[0], order); mm[1] = Math.max(mm[1], order); getMinMax(node.left, mm, order-1); getMinMax(node.right, mm, order+1); } |
Time complexity is O(n) and space complexity is O(n). n is the number of nodes on the tree.
We can calculate the min and max order of the tree first.
=====
if dont care about size of outer array .no need!
we know (worst case) max size of array_of_array is number of nodes. so allocate as much for outer array.
start +- for left/right node from max_size then decrement by max_size and BINGO. array index
during process, need min index found to mark start in outer array.!
This solution will not pass all the test cases –> It will print the nodes in their correct vertical levels, but they wont be in the correct order.
best answer
Both are O(n).
Can anybody please tell me what would be the time and space complexity of this program?
static class Node implements Comparable {
int value;
Node left, right;
public int level;
public int height;
public Node(int value) {
this.value = value;
}
public Node(int value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
@Override
public int compareTo(Node o) {
if (this.level == o.level) {
return this.height - o.height;
}
return this.level - o.level;
}
}
private PriorityQueue queue = new PriorityQueue();
private Node root;
public void verticalOrder() {
verticalOrder(root, 0);
while (!queue.isEmpty()) {
Node node = queue.poll();
System.out.print(node.value + " ");
}
}
private void verticalOrder(Node node, int level) {
if (node == null) {
return;
}
node.level = level;
queue.add(node);
verticalOrder(node.left, level - 1);
verticalOrder(node.right, level + 1);
}
Hi, so the time complexity for this solution is O(n) or O(nlogn)?
static void printVertically(TreeNode root, TreeMap<Integer, LinkedList> result, int level) {
if (root == null) {
return;
}
LinkedList list = result.get(level);
if (list == null) {
list = new LinkedList();
}
list.add(root.data);
result.put(level, list);
printVertically(root.left, result, level-1);
printVertically(root.right, result, level+1);
}
Same idea, alternate implementation (recursive). Note: I print the result, but returning a level list as shown in the example is trivially done with the same logic.
Note: this is also a Time O(N) impl and Space O(N).
Note 2: recursive implementation IMHO is way cleaner and will probably require less memory since we don’t have extra lists. Stack size shouldn’t be an issue considering that it only requires O(H) recursions (H = height of the tree)
class BinTreeNode {
public final T value;
public BinTreeNode left;
public BinTreeNode right;
}
void columnOrder(BinTreeNode n) {
Map<Integer, List<BinTreeNode>> columns = new HashMap();
columnOrder(n , columns, 0);
for (Integer idx : columns.keySet().stream().sorted().collect(Collectors.toList())) {
List<BinTreeNode> column = columns.get(idx);
for (BinTreeNode c : column) {
System.out.println(c.value);
}
}
}
void columnOrder(BinTreeNode n, Map<Integer, List<BinTreeNode>> columns, int column)
{
List<BinTreeNode> l = columns.computeIfAbsent(column, i -> new LinkedList());
l.add(n);
if (n.left != null) columnOrder(n.left , columns, column - 1);
if (n.right != null) columnOrder(n.right , columns, column + 1);
}