public List<List<Integer>> verticalOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if (root == null) return result;
        
        Map<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        Queue<Integer> cols = new LinkedList<Integer>();
        
        queue.add(root);
        cols.add(0);
        
        int min = 0, max = 0;
        while (!queue.isEmpty()) {
        	TreeNode node = queue.poll();
        	int col = cols.poll();
        	
        	if (!map.containsKey(col)) map.put(col, new ArrayList<Integer>());
        	map.get(col).add(node.val);
        	
        	if (node.left != null) {
        		queue.add(node.left);
        		cols.add(col - 1);
        		if (col <= min) min = col - 1;
        	}
        	
        	if (node.right != null) {
        		queue.add(node.right);
        		cols.add(col + 1);
        		if (col >= max) max = col + 1;
        	}
        }
        
        for (int i = min; i <= max; i++) {
        	result.add(map.get(i));
        }
        
        return result;
	}