Print a binary tree in an m*n 2D string array following these rules: 


The row number m should be equal to the height of the given binary tree.
The column number n should always be an odd number.
The root node's value (in string format) should be put in the exactly middle of the first row it can be put. The column and the row where the root node belongs will separate the rest space into two parts (left-bottom part and right-bottom part). You should print the left subtree in the left-bottom part and print the right subtree in the right-bottom part. The left-bottom part and the right-bottom part should have the same size. Even if one subtree is none while the other is not, you don't need to print anything for the none subtree but still need to leave the space as large as that for the other subtree. However, if two subtrees are none, then you don't need to leave space for both of them. 
Each unused space should contain an empty string "".
Print the subtrees following the same rules.


Example 1:

Input:
     1
    /
   2
Output:
[["", "1", ""],
 ["2", "", ""]]




Example 2:

Input:
     1
    / \
   2   3
    \
     4
Output:
[["", "", "", "1", "", "", ""],
 ["", "2", "", "", "", "3", ""],
 ["", "", "4", "", "", "", ""]]



Example 3:

Input:
      1
     / \
    2   5
   / 
  3 
 / 
4 
Output:

[["",  "",  "", "",  "", "", "", "1", "",  "",  "",  "",  "", "", ""]
 ["",  "",  "", "2", "", "", "", "",  "",  "",  "",  "5", "", "", ""]
 ["",  "3", "", "",  "", "", "", "",  "",  "",  "",  "",  "", "", ""]
 ["4", "",  "", "",  "", "", "", "",  "",  "",  "",  "",  "", "", ""]]



Note:
The height of binary tree is in the range of [1, 10].

Difficulty: interview

Starter code:

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
    self.val = val
    self.left = left
    self.right = right
class Solution:
    def printTree(self, root: TreeNode) -> List[List[str]]:
        

Solutions:
def get_tree_height(node, parent_node_height):
     if node is None:
         return 0
     node.height = parent_node_height + 1
     if node.left is None and node.right is None:
         return 1
     return max(get_tree_height(node.left, node.height), get_tree_height(node.right, node.height)) + 1
 
 def fill_in_array(result, node, root_index, width):
     if node is None:
         return
     result[node.height - 1][root_index] = str(node.val)
     new_width = width // 2
     fill_in_array(result, node.left, root_index - new_width // 2 - 1, new_width)
     fill_in_array(result, node.right, root_index + new_width // 2 + 1, new_width)
 
 class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         height = get_tree_height(root, 0)
         rows = height
         cols = 0
         for i in range(height):
             cols = cols * 2 + 1
         result = [[""] * cols for _ in range(rows)]
         fill_in_array(result, root, cols // 2, cols)
         return result

class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         def depth(root):
             if root is None:
                 return 0
             return max(depth(root.left),depth(root.right))+1
         def printT(x,root,dep):
             if root is not None:
                 ans[n-dep-1][x] = str(root.val)
                 printT(x-2**(dep-1),root.left,dep-1)
                 printT(x+2**(dep-1),root.right,dep-1)
                 
         
         n = depth(root) #2
         m = 2**n - 1  #3
         ans = [[""] * m for __ in range(n)]
         printT((m-1)//2,root,n-1) #1
         return ans
         


class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         def depth(node):
             if node is None:
                 return 0
             return 1+max(depth(node.left), depth(node.right))
         d = depth(root)
         
         result = [[""]*(2**d-1) for _ in range(d)]
         
         def helper(row, startcol, endcol, node):
             if node is None:
                 return
             
             col = (startcol+endcol) // 2
             result[row][col] = str(node.val)
             helper(row+1, startcol, col-1, node.left)
             helper(row+1, col+1, endcol, node.right)
             
 
             
         helper(0, 0, 2**d-2, root)
         return result

# Definition for a binary tree node.
 # class TreeNode(object):
 #     def __init__(self, x):
 #         self.val = x
 #         self.left = None
 #         self.right = None
 
 class Solution(object):
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         if not root:
             return []
         
         if root.left is root.right:
             return [[str(root.val)]]
         
         def mydepth(root):
             return max(mydepth(root.left), mydepth(root.right)) + 1 if root else 0
         
         depth = mydepth(root)
         n = 2 ** depth - 1
         ans = [["" for _ in range(n)] for _ in range(depth)]
         
         def dfs(root, currdepth, distance):
             if not root:
                 return 
             
             ans[currdepth][distance] = str(root.val)
             
             dfs(root.left, currdepth + 1, distance - 2 ** (depth - 2 - currdepth))
             dfs(root.right, currdepth + 1, distance +  2 ** (depth - 2 - currdepth))
             
         
         dfs(root, 0, 2 ** (depth - 1) - 1)
         return ans
             

class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         #The length of the entries should be 2^height - 1
         #The root will always be at the center
         #Recurse on the left and right subtrees pass the new centers and the lengths
         height = 0
         
         #O(n)
         def Dfs(node, currHeight):
             nonlocal height
             if node == None:
                 height = max(currHeight-1, height)
                 return
             Dfs(node.left, currHeight+1)
             Dfs(node.right, currHeight+1)
         Dfs(root, 1)
         
         #O(nlogn)
         ret = [[""]*(2**height - 1) for _ in range(height)]
         
         #O(n)
         def rec(node, currHeight, start, end):
             if(node == None):
                 return
             center = int((start + end)/2)
             ret[currHeight][center] = str(node.val)
             rec(node.left, currHeight+1, start, center-1)
             rec(node.right, currHeight+1, center+1, end)
         rec(root, 0, 0, 2**height-1)
         return ret

class Solution:
     def printTree(self, root):
         if not root:
             return [[]]
         from queue import Queue
         q, depth = Queue(), float('-inf')
         q.put((root, 1))
         while not q.empty():
             node, cur_depth = q.get()
             depth = max(depth, cur_depth)
             if node.left:
                 q.put((node.left, cur_depth + 1))
             if node.right:
                 q.put((node.right, cur_depth + 1))
         col = 0
         for _ in range(depth):
             col = 2 * col + 1
         res = [[''] * col for _ in range(depth)]
         q.put((root, 0, 0, col - 1))
         while not q.empty():
             node, depth, lo, hi = q.get()
             mid = (lo + hi) // 2
             res[depth][mid] = str(node.val)
             if node.left:
                 q.put((node.left, depth + 1, lo, mid - 1))
             if node.right:
                 q.put((node.right, depth + 1, mid + 1, hi))
         return res

"""
 满二叉树定位
 """
 
 def tree_height(tr, h):
     if not tr: return h
     lh, rh = tree_height(tr.left, h + 1), tree_height(tr.right, h + 1)
     return max(lh, rh)
     
 
 class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         def getHeight(root):
             if not root: return 0
             return 1 + max(getHeight(root.left), getHeight(root.right))
         
         h = getHeight(root)
         w = 2 ** h - 1
         w = (1 << h) - 1
         res = [[""]* w for _ in range(h)]
         
         def inorder(root,start,end,lev):
             if not root: return
             mid = (start + end) >> 1
             res[lev][mid] = str(root.val)
             inorder(root.left, start, mid, lev+1)
             inorder(root.right, mid + 1, end, lev+1)
         inorder(root, 0, w, 0)
         return res
         
         
         
         
         if (not root.left) and (not root.right): return [[str(root.val)]]
         th = tree_height(root, 0)
         w = (1 << th) - 1
         res = [[""] * w for i in range(th)]
         
         que = [(root, 0)]
         level = th - 1
         beg, end = 0, 1
         step = 1 << th
         while beg < end:
             level_cnt = 0
             for k in range(beg, end):
                 nd, i = que[k]
                 # print(th - 1 - level, step, nd.val, i, ((i + 1) * step) - (step >> 1) - 1)
                 #  ((i + 1) * step) - (step >> 1) - 1 # 第i个step块的中间位置，0始下标
                 res[th - 1 - level][((i + 1) * step) - (step >> 1) - 1] = str(nd.val)
                 if nd.left:
                     que.append((nd.left, i << 1))
                     level_cnt += 1
                 if nd.right:
                     que.append((nd.right, (i << 1) + 1))
                     level_cnt += 1
                 beg += 1
             level -= 1
             step >>= 1
             end += level_cnt
         return res
                     
 """
 [1,2]
 [1,2,3, null, null,4,5]
 [1]
 """
 
         

class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         
         def depth(node):
             if not node:
                 return 0
             return 1 + max(depth(node.left), depth(node.right))
         
         dep = depth(root)
         wid = 2 ** dep - 1
         frame = [['' for j in range(wid) ] for i in range(dep)]
         
         def filler(node, level, low, high):
             if not node or low > high:
                 return
             mid = (low + high) // 2
             frame[level][mid] = str(node.val)
             filler(node.left, level + 1, low, mid)
             filler(node.right, level + 1, mid + 1, high)
         
         filler(root, 0, 0, wid)
         return frame
             


class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         def h(node):
             if not node:
                 return 0
             return 1+max(h(node.left), h(node.right))
         
         height = h(root)
         m = height
         n = 2**height-1
         ret = [['' for _ in range(n)] for __ in range(m)]
         
         def put(node, i, l, r):
             mid = (l+r)//2
             ret[i][mid] = str(node.val)
             if node.left:
                 put(node.left, i+1, l, mid-1)
             if node.right:
                 put(node.right, i+1, mid+1, r)
                 
         put(root, 0, 0, n-1)
         return ret

class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         def getHeight(root):
             if not root: return 0
             return 1 + max(getHeight(root.left), getHeight(root.right))
         
         h = getHeight(root)
         w = 2**h - 1
         res = [[""]*w for _ in range(h)]
         
         def preorder(root, start, end, h):
             if not root: return 
             mid = (start + end) // 2
             res[h][mid] = str(root.val)
             preorder(root.left, start, mid, h+1)
             preorder(root.right, mid+1, end, h+1)
         
         preorder(root, 0, w, 0)
         return res
             
             


class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         level = [root]
         tree = []
         while any(level):
             tree.append([str(node.val) if node else "" for node in level])
             level = [leaf for node in level for leaf in ((node.left,node.right) if node else(None,None))]
         ans = [["" for _ in range(2**len(tree)-1) ] for _ in range(len(tree))]
         for r in range(len(tree)):
             i = -2**(len(tree)-r-1)-1
             for c in tree[r]:
                 i += 2**(len(tree)-r)
                 ans[r][i] = c
         return ans

class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         # helper functions
         def depth(root):
             if root is None:
                 return 0
             return 1 + max(depth(root.left), depth(root.right))
         
         def fill(res, root, i, l, r):
             if root is None:
                 return
             res[i][(l + r) // 2] = str(root.val)
             fill(res, root.left, i + 1, l, (l + r) // 2)
             fill(res, root.right, i + 1, (l + r) // 2 + 1, r)
         
         # array filled with ""
         height = depth(root)
         width = pow(2, height) - 1
         ans = []
         for i in range(height):
             ans.append([])
             for j in range(width):
                 ans[i].append("")
         
         i = 0
         l = 0
         r = width
         
         fill(ans, root, 0, 0, width - 1)
         
 
         
         return ans


class Solution:
     def printTree(self, root):
         """
         :type root: TreeNode
         :rtype: List[List[str]]
         """
         if not root: 
             return [""]
         def getDepth(root):
             if not root:
                 return 0
             return 1 + max(getDepth(root.left), getDepth(root.right))
         d = getDepth(root)
         cols = 2 ** d - 1
         result = [["" for i in range(cols)] for j in range(d)]
         def helper(root, d, pos):
             result[-d - 1][pos] = str(root.val)
             if root.left: helper(root.left, d - 1, pos - 2 ** (d - 1))
             if root.right: helper(root.right, d - 1, pos + 2 ** (d - 1))
         helper(root, d - 1, 2 ** (d - 1) - 1)
         return result